关于线程终止问题。。。大神帮忙

Ghost_520 2014-08-18 11:13:01
我使用线程管理器并发若干子线程, 个数由队列的大小决定,我想实现只要其中一个子线程计算失败,我就停止所有的运行或不运行的子线程,现在的问题是, 我遍历子线程列表, f.cancel(true); 这一段代码没有成功,后台还是继续输出了 System.out 的输出信息, 不知道是不是哪写错了,求帮忙。。。

public Map<String, Object> dataExtract() throws InterruptedException{
// 装载数据表池
DataTabPool.getInstance().loadTabPool();

final ArrayBlockingQueue<String> ABQ = DataTabPool.getInstance().getABQ(); //获取数据表池队列,加载到并行线程中

final Map<String, Object> returnMap = new HashMap<String, Object>();

// 用于存放每层抽取线程任务列表,便于控制所有的线程任务
final List<Future<Map<String, Object>>> list = new ArrayList<Future<Map<String, Object>>>();

// 控制线程并行运行
final CountDownLatch begin = new CountDownLatch(ABQ.size());
// 线程一并等待,同时开始运行。任何一个验证出现错误的时候,能在任务列表中找到任务并停止
final CyclicBarrier barrierOne = new CyclicBarrier(ABQ.size());

// 根据列队大小定义并发线程数
final ExecutorService exec = Executors.newFixedThreadPool(ABQ.size());

// 并行子线程
for (int index = 0; index < ABQ.size(); index++) {
final int NO = index + 1;

if(!DataExtractMain.this.mark){
break;
}
list.add(exec.submit(new Callable<Map<String, Object>>() {
public Map<String, Object> call() throws Exception {
try {

// 如果当前计数为零,则此方法立即返回。
barrierOne.await();

// 动态从池中取出表名
String tableName = DataTabPool.getInstance().takeTab();
System.out.println("No." + NO + " :" + tableName);

// 开始抽数业务代码
Map<String,Object[]> resultMap = new DataExtractWork().extractDataAndSave(tableName) ;

// 当抽取失败的时候,取消任务列表中所有任务,同时修改标记位,停止整个任务管理器,之后的多有操作也不用执行
if (resultMap == null) {
DataExtractMain.this.mark = false;
// 循环遍历停掉管理器中的子线程
for (Future<Map<String, Object>> f : list) {
f.cancel(true);
}
}

} finally {
begin.countDown();
}
return null;
}
}));
}

System.out.println("Extract Start");
begin.await();
System.out.println("Extract Over");
exec.shutdown();
// 判断标志,来决定是否继续后续操作
if (exec.isTerminated()) {
System.out.println("errorList size : " + errorList.size());
return null;
}else{
return returnMap;
}
}
...全文
194 点赞 收藏 7
写回复
7 条回复
Ghost_520 2015年04月03日
问题已解决, 我用CopyOnWriteArrayList 收集成功线程个数, 最后判定是否完成所有线程
boolean isDone = true;
            while(isDone){
            	for(Future<Map<String,String>> future: futureList){
            		if(future.isDone()){
            			// 如果该线程完成了, 则删除该future
            			futureList.remove(future);
            		}
            		if(futureList.size()==0){
            			// 当线程集合为空时,表示所有线程执行完毕
            			isDone = false;
            			break;
            		}
            	}
            }
回复 点赞
须等待 2014年08月18日
你要 去了解线程是怎么终止的。不是你的代码有问题,是你对线程终止的理解有问题。 有几种情况可以让线程立马停止:某些阻塞的时候下被调用cancel,线程中主动检查cancel标识。 怎么理解上面那句话,就是说如果不存在阻塞的情况下,系统认为你的线程很快就要结束了,其不会也不能显式的把这个线程干掉。当阻塞的时候,可以显式的干掉,系统接收到信号以后会强制从阻塞状态中恢复过来。 所以你要做的是,在你线程的执行过程中显式的检查cancel标识,否则线程是不会在没有阻塞标识的情况下自己停止的
回复 点赞
Ghost_520 2014年08月18日
没人回复, 帖子果断加分到 100 分,, 顶起啊, 谢谢啦
回复 点赞
商科程序员 2014年08月18日
可以用监控者,执行者的模式。
回复 点赞
须等待 2014年08月18日
引用 3 楼 Ghost_520 的回复:
[quote=引用 2 楼 ygycomon 的回复:] 你要 去了解线程是怎么终止的。不是你的代码有问题,是你对线程终止的理解有问题。 有几种情况可以让线程立马停止:某些阻塞的时候下被调用cancel,线程中主动检查cancel标识。 怎么理解上面那句话,就是说如果不存在阻塞的情况下,系统认为你的线程很快就要结束了,其不会也不能显式的把这个线程干掉。当阻塞的时候,可以显式的干掉,系统接收到信号以后会强制从阻塞状态中恢复过来。 所以你要做的是,在你线程的执行过程中显式的检查cancel标识,否则线程是不会在没有阻塞标识的情况下自己停止的
你说的大概懂了, 但是我看了API , Future 里没有获取线程状态的方法呢[/quote] 这个你就要查一下了。
回复 点赞
Ghost_520 2014年08月18日
引用 2 楼 ygycomon 的回复:
你要 去了解线程是怎么终止的。不是你的代码有问题,是你对线程终止的理解有问题。 有几种情况可以让线程立马停止:某些阻塞的时候下被调用cancel,线程中主动检查cancel标识。 怎么理解上面那句话,就是说如果不存在阻塞的情况下,系统认为你的线程很快就要结束了,其不会也不能显式的把这个线程干掉。当阻塞的时候,可以显式的干掉,系统接收到信号以后会强制从阻塞状态中恢复过来。 所以你要做的是,在你线程的执行过程中显式的检查cancel标识,否则线程是不会在没有阻塞标识的情况下自己停止的
你说的大概懂了, 但是我看了API , Future 里没有获取线程状态的方法呢
回复 点赞
发动态
发帖子
Java SE
创建于2007-09-28

3.4w+

社区成员

30.7w+

社区内容

Java 2 Standard Edition
社区公告
暂无公告