论坛首页 Java企业应用论坛

Java多线程--让主线程等待所有子线程执行完毕

浏览 54826 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-01-28  
icyiwh 写道

  当然记数也是比较可以的简单的方式(线程开始(执行时)记数器加1,执行完成时减1),记数器为0时即所有线程已经完成
  PS:但记数器有一个问题需要考虑. 如线程1开始,如果线程1在线程2开始前结束,那记数器也是0,这种情况要考虑

最后补充的问题我也注意到了,有什么好的解决方法吗?我现在的做法是让主线程睡上2秒,等待子线程开始,但是这样似乎还是不安全,是不是应该wait一下?有没有更好的方法啊
0 请登录后投票
   发表时间:2010-01-28  
zli.ray 写道
又一个轮子。
用java.util.concurrent.CountDownLatch就可以了。

即使在1.4中,CountDownLatch用不了,lz的代码里主线程的while循环中,至少应该sleep一下,不然很耗吧。

看了一下api,好像是可以解决我的这个问题。谢谢,受教了!不过骂人"轮子"就太不厚道了
0 请登录后投票
   发表时间:2010-01-28  
既然举例,为何不按API来,存在隐患,误导他人。
0 请登录后投票
   发表时间:2010-01-28   最后修改:2010-01-28
http://www.iteye.com/topic/363625

仔细看看:“5、CountDownLatch”
0 请登录后投票
   发表时间:2010-01-28  
jahcy 写道
是我的错,join是串行到主线程........哈哈

你没仔细看我的帖子啊,我的第一种做法就是你这样的啊,结果是顺序执行了,没有并发
0 请登录后投票
   发表时间:2010-01-28  
zmcsut 写道
既然举例,为何不按API来,存在隐患,误导他人。

因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
0 请登录后投票
   发表时间:2010-01-28  
NetBus 写道
http://www.iteye.com/topic/363625

仔细看看:“5、CountDownLatch”

谢谢!
0 请登录后投票
   发表时间:2010-01-28  
yadsun 写道
zli.ray 写道
又一个轮子。
用java.util.concurrent.CountDownLatch就可以了。

即使在1.4中,CountDownLatch用不了,lz的代码里主线程的while循环中,至少应该sleep一下,不然很耗吧。

看了一下api,好像是可以解决我的这个问题。谢谢,受教了!不过骂人"轮子"就太不厚道了

晕,lz好像缺乏常识。我没有骂人。“不要重复发明轮子”,这句话没听过?
0 请登录后投票
   发表时间:2010-01-28  
给你个例子吧,以前学习CountDownLatch 时学的,最简单的使用,主线程启动多个工作线程后等待,最后一个工作线程完成时通知主线程:

private class Driver {
public void execute() {
final int workerCount = 10;
CountDownLatch doneSignal = new CountDownLatch(workerCount);
Executor e = Executors.newCachedThreadPool();

System.out.println("driver : start worker");
for (int i = 0; i < workerCount; ++i) {
e.execute(new Worker(doneSignal, i));
}

try {
System.out.println("driver : wait for all worker finish");
doneSignal.await();
System.out.println("driver : all worker done");
} catch (InterruptedException e1) {
e1.printStackTrace();
}

}
}

private class Worker implements Runnable {
private final CountDownLatch doneSignal;
private final int i;

public Worker(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
}

public void run() {
String name = "worker" + (i + 1);

System.out.println(name + " start to work");
doWork();
System.out.println(name + " finish work");

doneSignal.countDown();
}

void doWork() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
0 请登录后投票
   发表时间:2010-01-28   最后修改:2010-01-28
上面这个例子不是足够精确,尤其是工作线程比较多的时候,主线程逐个启动工作线程的时候会很长,如果工作线程执行时间很短,会出现某些先启动的工作线程已经结束而有些线程都还没有被主线程启动。

给一个更加复杂的例子,工作线程启动后会停下来,等所有工作线程都启动完成,然后主线程再通知所有工作线程可以开始干活,呵呵,比较啰嗦:

private class Driver {
public void execute() {
final int workerCount = 10;
CountDownLatch lunchSignal = new CountDownLatch(workerCount);
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(workerCount);

System.out.println("driver: begin to lunch worker thread");
for (int i = 0; i < workerCount; ++i) {
Thread t = new Thread(new Worker(lunchSignal, startSignal,
doneSignal));
t.setName("worker" + (i + 1));
t.start();
}

try {
lunchSignal.await();
System.out.println("driver: all worker lunched");
} catch (InterruptedException e1) {
e1.printStackTrace();
}

System.out
.println("driver: send signal to all worker to start work");
startSignal.countDown();

try {
System.out.println("driver: wait for all worker");
doneSignal.await();
System.out.println("driver: all worker finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

private class Worker implements Runnable {
private final CountDownLatch lunchSignal;
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;

Worker(CountDownLatch lunchSignal, CountDownLatch startSignal,
CountDownLatch doneSignal) {
this.lunchSignal = lunchSignal;
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}

public void run() {
String name = Thread.currentThread().getName();
try {
System.out.println(name + " lunched and wait for start signal");
lunchSignal.countDown();
lunchSignal.await();

startSignal.await();
System.out.println(name + " start to do work");

doWork();
System.out.println(name
+ " finish work and wait for other worker");

doneSignal.countDown();
doneSignal.await();
System.out.println(name + " quit");
} catch (InterruptedException ex) {
}
}

private void doWork() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics