- 浏览: 181361 次
- 性别:
- 来自: 上海
最新评论
-
dongdong12345_:
感谢楼主,帮到了我
根据当前日期算前一年、前一月、前一天(java基础) -
kyson:
lz活生生地弄了一个线程池啊。。
Java多线程--让主线程等待所有子线程执行完毕 -
liyong635:
楼主太给力了~赞一个~~
eclipse birt使用脚本实现换行 -
xining:
其实可以使用 ThreadGroup 调用ThreadG ...
Java多线程--让主线程等待所有子线程执行完毕 -
guowusmiile:
何必这么麻烦,其实只需要一个for循环,就可以解决LZ标题问题 ...
Java多线程--让主线程等待所有子线程执行完毕
朋友让我帮忙写个程序从文本文档中导入数据到oracle数据库中,技术上没有什么难度,文档的格式都是固定的只要对应数据库中的字段解析就行了,关键在于性能。
数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下
结果是几乎在for循环结束的瞬间就执行了主线程打印总共用时的语句,原因是所有的子线程是并发执行的,它们运行时主线程也在运行,这就引出了一个问题即本文标题如何"让主线程等待所有子线程执行完毕"。试过在每个子线程开始后加上t.join(),结果是所有线程都顺序执行,这就失去了并发的意义了,显然不是我想要的。
网上Google了很久也没有找到解决方案,难道就没有人遇到过这种需求吗?还是这个问题太简单了?无耐只得自己想办法了...
最后我的解决办法是,自定义一个ImportThread类继承自java.lang.Thread,重载run()方法,用一个List属性保存所有产生的线程,这样只要判断这个List是否为空就知道还有没有子线程没有执行完了,类代码如下:
主线程中代码:
打印的结果是:
main开始
Thread-1开始...
Thread-5开始...
Thread-0开始...
Thread-2开始...
Thread-3开始...
Thread-4开始...
Thread-5结束.
Thread-4结束.
Thread-2结束.
Thread-0结束.
Thread-3结束.
Thread-1结束.
main结束.
总共用时:20860millions
可以看到main线程是等所有子线程全部执行完后才开始执行的。
==================================================以下为第二次编辑===============================================
上面的方法有一个隐患:如果线程1开始并且结束了,而其他线程还没有开始此时runningThreads的size也为0,主线程会以为所有线程都执行完了。解决办法是用一个非简单类型的计数器来取代List型的runningThreads,并且在线程创建之前就应该设定好计数器的值。
MyCountDown类
ImportThread类
主线程中
打印结果:
main开始
Thread-2开始...
Thread-1开始...
Thread-0开始...
Thread-3开始...
Thread-5开始...
Thread-4开始...
Thread-5结束. 还有5 个线程
Thread-1结束. 还有4 个线程
Thread-4结束. 还有3 个线程
Thread-2结束. 还有2 个线程
Thread-3结束. 还有1 个线程
Thread-0结束. 还有0 个线程
main结束.
更简单的方法:使用java.util.concurrent.CountDownLatch代替MyCountDown,用await()方法代替while(true){...}
ImportThread类
主线程中
打印结果:
main开始
Thread-1开始...
Thread-0开始...
Thread-2开始...
Thread-3开始...
Thread-4开始...
Thread-5开始...
Thread-0结束. 还有5 个线程
Thread-1结束. 还有4 个线程
Thread-4结束. 还有3 个线程
Thread-2结束. 还有2 个线程
Thread-5结束. 还有1 个线程
Thread-3结束. 还有0 个线程
main结束.
受教,确实是这样。最开始以为自己的想法是错误的,原来start -> join, start -> join这样是确实相当于一个个顺序执行。
如果是startA,startB, joinA,joinB确实能实现同样的功能
请看完整文再说,join()方法已经讨论过n次了,如果你有好方法请帖出来,
就是个join,
是你自己不清楚.
请看完整文再说,join()方法已经讨论过n次了,如果你有好方法请帖出来,
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
我没有用Executor会不会有隐患?
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
好吧,我承认,首先没有认真读楼主的例子,我有错。
但是既然你提出有隐患了,那么你可否把隐患指出?我虚心的接受指导。
因为我的例子只是简单的展示一下怎么用而已,且不考虑线程同时开启的问题,只考虑不同时结束的问题。写法上也是很随意,但如果真有隐患麻烦您指出一下,让我知道自己的错误。
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
看了一下api,好像是可以解决我的这个问题。谢谢,受教了!不过骂人"轮子"就太不厚道了
晕,lz好像缺乏常识。我没有骂人。“不要重复发明轮子”,这句话没听过?
谢谢!
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
你没仔细看我的帖子啊,我的第一种做法就是你这样的啊,结果是顺序执行了,没有并发
数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis()在最后一个子进程结束后记录当前时间,两次一减得到的时间差即为总共的用时,代码如下
long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记 for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程 Runnable r = new Runnable(){ @Override public void run(){ System.out.println(Thread.currentThread().getName() + "开始"); //做一些事情... ... System.out.println(Thread.currentThread().getName() + "结束."); } } Thread t = new Thread(r); t.start(); } System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记 long tEnd = System.currentTimeMillis(); System.out.println("总共用时:"+ (tEnd - tStart) + "millions");
结果是几乎在for循环结束的瞬间就执行了主线程打印总共用时的语句,原因是所有的子线程是并发执行的,它们运行时主线程也在运行,这就引出了一个问题即本文标题如何"让主线程等待所有子线程执行完毕"。试过在每个子线程开始后加上t.join(),结果是所有线程都顺序执行,这就失去了并发的意义了,显然不是我想要的。
网上Google了很久也没有找到解决方案,难道就没有人遇到过这种需求吗?还是这个问题太简单了?无耐只得自己想办法了...
最后我的解决办法是,自定义一个ImportThread类继承自java.lang.Thread,重载run()方法,用一个List属性保存所有产生的线程,这样只要判断这个List是否为空就知道还有没有子线程没有执行完了,类代码如下:
public class ImportThread extends Thread { private static List<Thread> runningThreads = new ArrayList<Thread>(); public ImportThread() { } @Override public void run() { regist(this);//线程开始时注册 System.out.println(Thread.currentThread().getName() + "开始...");//打印开始标记 //做一些事情... ... unRegist(this);//线程结束时取消注册 System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记 } public void regist(Thread t){ synchronized(runningThreads){ runningThreads.add(t); } } public void unRegist(Thread t){ synchronized(runningThreads){ runningThreads.remove(t); } } public static boolean hasThreadRunning() { return (runningThreads.size() > 0);//通过判断runningThreads是否为空就能知道是否还有线程未执行完 } }
主线程中代码:
long tStart = System.currentTimeMillis(); System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记 for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程 Thread t = new ImportThread(); t.start(); } while(true){//等待所有子线程执行完 if(!ImportThread.hasThreadRunning()){ break; } Thread.sleep(500); } System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记 long tEnd = System.currentTimeMillis(); System.out.println("总共用时:"+ (tEnd - tStart) + "millions");
打印的结果是:
main开始
Thread-1开始...
Thread-5开始...
Thread-0开始...
Thread-2开始...
Thread-3开始...
Thread-4开始...
Thread-5结束.
Thread-4结束.
Thread-2结束.
Thread-0结束.
Thread-3结束.
Thread-1结束.
main结束.
总共用时:20860millions
可以看到main线程是等所有子线程全部执行完后才开始执行的。
==================================================以下为第二次编辑===============================================
上面的方法有一个隐患:如果线程1开始并且结束了,而其他线程还没有开始此时runningThreads的size也为0,主线程会以为所有线程都执行完了。解决办法是用一个非简单类型的计数器来取代List型的runningThreads,并且在线程创建之前就应该设定好计数器的值。
MyCountDown类
public class MyCountDown { private int count; public MyCountDown(int count){ this.count = count; } public synchronized void countDown(){ count--; } public synchronized boolean hasNext(){ return (count > 0); } public int getCount() { return count; } public void setCount(int count) { this.count = count; } }
ImportThread类
public class ImportThread extends Thread { private MyCountDown c; public ImportThread(MyCountDown c) { this.c = c; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "开始...");//打印开始标记 //Do something c.countDown();//计时器减1 System.out.println(Thread.currentThread().getName() + "结束. 还有" + c.getCount() + " 个线程");//打印结束标记 } }
主线程中
System.out.println(Thread.currentThread().getName() + "开始");//打印开始标记 MyCountDown c = new MyCountDown(threadNum);//初始化countDown for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程 Thread t = new ImportThread(c); t.start(); } while(true){//等待所有子线程执行完 if(!c.hasNext()) break; } System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记
打印结果:
main开始
Thread-2开始...
Thread-1开始...
Thread-0开始...
Thread-3开始...
Thread-5开始...
Thread-4开始...
Thread-5结束. 还有5 个线程
Thread-1结束. 还有4 个线程
Thread-4结束. 还有3 个线程
Thread-2结束. 还有2 个线程
Thread-3结束. 还有1 个线程
Thread-0结束. 还有0 个线程
main结束.
更简单的方法:使用java.util.concurrent.CountDownLatch代替MyCountDown,用await()方法代替while(true){...}
ImportThread类
public class ImportThread extends Thread { private CountDownLatch threadsSignal; public ImportThread(CountDownLatch threadsSignal) { this.threadsSignal = threadsSignal; } @Override public void run() { System.out.println(Thread.currentThread().getName() + "开始..."); //Do somethings threadsSignal.countDown();//线程结束时计数器减1 System.out.println(Thread.currentThread().getName() + "结束. 还有" + threadsSignal.getCount() + " 个线程"); } }
主线程中
CountDownLatch threadSignal = new CountDownLatch(threadNum);//初始化countDown for (int ii = 0; ii < threadNum; ii++) {//开threadNum个线程 final Iterator<String> itt = it.get(ii); Thread t = new ImportThread(itt,sql,threadSignal); t.start(); } threadSignal.await();//等待所有子线程执行完 System.out.println(Thread.currentThread().getName() + "结束.");//打印结束标记
打印结果:
main开始
Thread-1开始...
Thread-0开始...
Thread-2开始...
Thread-3开始...
Thread-4开始...
Thread-5开始...
Thread-0结束. 还有5 个线程
Thread-1结束. 还有4 个线程
Thread-4结束. 还有3 个线程
Thread-2结束. 还有2 个线程
Thread-5结束. 还有1 个线程
Thread-3结束. 还有0 个线程
main结束.
评论
32 楼
jahcy
2010-01-28
srdrm 写道
难道不会变通一下?
你是 for 循环中,start, join 一起来, 你不会改为只 start thread, 同时将thread保存起来. 全部 start 完毕后再一个个join, 甚至带上时间 join(1000)
你是 for 循环中,start, join 一起来, 你不会改为只 start thread, 同时将thread保存起来. 全部 start 完毕后再一个个join, 甚至带上时间 join(1000)
受教,确实是这样。最开始以为自己的想法是错误的,原来start -> join, start -> join这样是确实相当于一个个顺序执行。
如果是startA,startB, joinA,joinB确实能实现同样的功能
31 楼
heqishan
2010-01-28
刚刚开始学习线程,mark了。呵呵
30 楼
oaklet
2010-01-28
java线程是能并发了!
oracle数据库是并发入库的吗。
oracle数据库是并发入库的吗。
29 楼
srdrm
2010-01-28
细节就是结束的线程, 需要移除. 不再join尝试它了.
在这里, 个人认为LinkedList 是比较合适作为保存Thread的集合.
在这里, 个人认为LinkedList 是比较合适作为保存Thread的集合.
28 楼
srdrm
2010-01-28
难道不会变通一下?
你是 for 循环中,start, join 一起来, 你不会改为只 start thread, 同时将thread保存起来. 全部 start 完毕后再一个个join, 甚至带上时间 join(1000)
你是 for 循环中,start, join 一起来, 你不会改为只 start thread, 同时将thread保存起来. 全部 start 完毕后再一个个join, 甚至带上时间 join(1000)
27 楼
icefishc
2010-01-28
yadsun 写道
srdrm 写道
难道你不知道线程有等待另一线程直到另一线程退出的方法?
join()
join()
请看完整文再说,join()方法已经讨论过n次了,如果你有好方法请帖出来,
就是个join,
是你自己不清楚.
26 楼
yadsun
2010-01-28
srdrm 写道
难道你不知道线程有等待另一线程直到另一线程退出的方法?
join()
join()
请看完整文再说,join()方法已经讨论过n次了,如果你有好方法请帖出来,
25 楼
srdrm
2010-01-28
难道你不知道线程有等待另一线程直到另一线程退出的方法?
join()
join()
24 楼
srdrm
2010-01-28
用多线程导入是失败的设计
23 楼
yadsun
2010-01-28
zmcsut 写道
yadsun 写道
zmcsut 写道
既然举例,为何不按API来,存在隐患,误导他人。
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
我没有用Executor会不会有隐患?
22 楼
jahcy
2010-01-28
zmcsut 写道
yadsun 写道
zmcsut 写道
既然举例,为何不按API来,存在隐患,误导他人。
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
好吧,我承认,首先没有认真读楼主的例子,我有错。
但是既然你提出有隐患了,那么你可否把隐患指出?我虚心的接受指导。
因为我的例子只是简单的展示一下怎么用而已,且不考虑线程同时开启的问题,只考虑不同时结束的问题。写法上也是很随意,但如果真有隐患麻烦您指出一下,让我知道自己的错误。
21 楼
mgbin
2010-01-28
为什么要用JAVA装载文本文件,ORACLE的装载工具不是更方便吗
20 楼
zmcsut
2010-01-28
yadsun 写道
zmcsut 写道
既然举例,为何不按API来,存在隐患,误导他人。
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
按skydream的来,别用jahcy的例子,有隐患。
19 楼
skydream
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();
}
}
}
给一个更加复杂的例子,工作线程启动后会停下来,等所有工作线程都启动完成,然后主线程再通知所有工作线程可以开始干活,呵呵,比较啰嗦:
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();
}
}
}
18 楼
skydream
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();
}
}
}
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();
}
}
}
17 楼
zli.ray
2010-01-28
yadsun 写道
zli.ray 写道
又一个轮子。
用java.util.concurrent.CountDownLatch就可以了。
即使在1.4中,CountDownLatch用不了,lz的代码里主线程的while循环中,至少应该sleep一下,不然很耗吧。
用java.util.concurrent.CountDownLatch就可以了。
即使在1.4中,CountDownLatch用不了,lz的代码里主线程的while循环中,至少应该sleep一下,不然很耗吧。
看了一下api,好像是可以解决我的这个问题。谢谢,受教了!不过骂人"轮子"就太不厚道了
晕,lz好像缺乏常识。我没有骂人。“不要重复发明轮子”,这句话没听过?
16 楼
yadsun
2010-01-28
NetBus 写道
http://www.iteye.com/topic/363625
仔细看看:“5、CountDownLatch”
仔细看看:“5、CountDownLatch”
谢谢!
15 楼
yadsun
2010-01-28
zmcsut 写道
既然举例,为何不按API来,存在隐患,误导他人。
因为之前没有找到api,google许久也没有找到合适的方法,稍候修改一下,谢谢提醒
14 楼
yadsun
2010-01-28
jahcy 写道
是我的错,join是串行到主线程........哈哈
你没仔细看我的帖子啊,我的第一种做法就是你这样的啊,结果是顺序执行了,没有并发
13 楼
NetBus
2010-01-28
http://www.iteye.com/topic/363625
仔细看看:“5、CountDownLatch”
仔细看看:“5、CountDownLatch”
发表评论
-
Jboss 5启动报IO异常的解决方法
2010-10-29 13:52 2996今天启动jboss报了个诡异的IO异常 错误代码: 引用 20 ... -
Ejb3持久化实体时的异常
2010-06-01 14:31 1357对某个Entity进行持久化操作时发生如下异常 Caused ... -
eclipse birt使用脚本实现换行
2010-02-02 13:20 4991使用Eclipse Birt有 ... -
java操作XMLType的几种方法
2010-02-02 13:16 5128XMLType是oracle数据库特有的数据类型可以 ... -
JavaEye怎么回事?s\cript竟成敏感词?
2010-02-02 13:14 1273今天本来准备写个帖子,结果不让提交 您的文章当中包含了敏感关键 ... -
未给Editor指定icon引发的异常
2010-01-18 16:27 1244扩展elcipse.ui.editor时报了org.ecl ... -
Eclipse Birt的列绑定错误
2010-01-15 16:52 1995今天用eclipse birt做报表时出现了一个错误困扰 ... -
根据当前日期算前一年、前一月、前一天(java基础)
2010-01-13 15:17 12722问题的本身没有什么难度,但是要想一下子找到一个现成的方法 ... -
Swt/Jface tableviewer 加入filter ,改变行的颜色
2009-12-15 11:18 2521原帖出处:http://blog.csdn.net/alex ... -
Eclipse Birt使用动态sql创建data set
2009-12-10 15:18 6300Eclipse Birt可以使用sql query来创 ... -
SSH框架中向数据库存取图片
2009-10-20 22:36 4578以前一直觉得向数据库中存图片是件挺麻烦的事情,今天自 ... -
Java中带复选框的树的级联选择与取消
2009-07-23 14:40 3785需要实现如下的功能: 当选中树中的某一节点时, ...
相关推荐
在Java多线程编程中,有时我们需要确保所有子线程执行完毕后再进行后续操作,例如在并发测试、数据聚合或资源清理等场景。本篇文章将详细介绍五种在Java中等待所有子线程执行完的方法。 ### 方法一:使用`sleep`...
在Java多线程编程中,有时我们需要确保主线程在所有子线程完成执行后再继续执行。这在处理大量并发任务,比如数据导入、并行计算等场景中是常见的需求。以下是如何实现这一功能的详细解释。 首先,让我们理解为什么...
Java 主线程等待子线程执行完毕 Java 中的多线程编程是非常重要的一部分,特别是在需要并发执行多个任务的情况下。然而,在某些情况下,我们需要等待所有子线程执行完毕后再继续执行主线程的剩余动作。这时,我们...
要解决“让主线程等待所有子线程执行完毕”的问题,可以采用以下策略: 1. 使用`join()`方法:如提到的,直接在每个子线程的`start()`之后调用`t.join()`,会导致所有线程按顺序执行。这是因为`join()`会让主线程...
总的来说,Java提供了丰富的多线程同步机制,可以根据实际需求选择合适的方法来实现“主线程等待所有子线程完成再继续”的功能。在并发编程中,理解并灵活运用这些工具对于提高程序效率和避免死锁等问题至关重要。
在多线程编程中,有时我们需要确保主线程在所有子线程执行完毕后才继续执行。这通常是为了保证数据的一致性或者按照特定顺序完成任务。"主线程等待子多线程(无结果返回)执行完成再继续执行"这个主题就涉及到如何在...
本篇文章将深入探讨如何在Python中实现多线程,并让主线程等待所有子线程结束。 首先,我们需要了解Python中的`threading`模块,它是Python标准库中用于处理多线程的模块。在示例代码中,我们创建了两个函数`a()`和...
自己学着编写的一个JAVA多线程程序,该程序实现的功能是:在主线程main中创建两个子线程,A和B,线程A先运行,再运行B线程,当两个子线程都运行完毕后,才运行主线程,并最终结束整个程序的运行。 希望该程序对初学...
为解决这个问题,我们需要使用同步机制,如Java中的`join()`方法或C#的`Thread.Join()`,让主线程等待所有子线程完成后再继续执行。当调用`join()`方法时,主线程会被阻塞,直到被调用的线程执行完毕。 例如,在...
// 主线程等待thread1执行完毕 thread1.join(); ``` **异常处理**: 在多线程环境中,每个线程都有自己的异常处理机制。主线程不会捕获子线程抛出的异常,因此在子线程中需要妥善处理异常,避免程序意外终止。 总...
1. **主线程等待子线程完成**:在多线程环境中,主线程有时需要等待所有子线程执行完毕后才进行后续处理,如清理资源或汇总子线程的计算结果。 2. **线程间数据同步**:当一个线程依赖于另一个线程产生的数据时,...
然后调用`s.join()`,这就意味着主线程会暂停执行,直到子线程`s`执行完毕。这种行为确保了子线程的操作先于主线程的后续操作完成。 在`join()`方法的源码分析中,我们可以看到两个重载版本:一个不带参数,一个带...
线程是程序执行流的最小单元,一个标准的程序只能执行一个任务,而使用多线程技术可以让程序同时执行多个任务,从而提高程序的性能。 #### 2. 线程与进程的区别 - **进程**:每个进程都有独立的代码和数据空间(即...
当主线程结束时,所有由主线程创建的子线程也将随之结束。这是Java虚拟机(JVM)的行为,确保了程序的整洁关闭。 #### 4. 线程的终止 除了自然结束外,线程还可以通过调用`stop()`方法强制停止。然而,此方法已被...
2. **主线程等待子线程**:接着,主线程通过调用`join()`方法等待子线程执行完毕。 3. **子线程执行完毕**:子线程执行完毕后,主线程继续执行后续逻辑。 通过这种方式,我们可以清晰地控制线程之间的执行顺序。 ...
在Java多线程编程中,CountDownLatch是一个非常重要的同步工具类,它可以帮助我们协调多个线程之间的交互。本文将深入探讨CountDownLatch的工作原理、使用场景以及相关源码分析。 CountDownLatch是一个计数器,初始...
8. 调用`countDownLatch.await()`,主线程会阻塞等待直到所有子线程执行完毕。 需要注意的是,为了确保线程安全,文件读取和重命名操作应当采取措施避免冲突,例如可以在读取文件时使用文件锁机制,或是在重命名...
每个Java应用程序至少有一个线程,称为主线程,它是程序执行的起点。线程的创建通常是通过实现`Runnable`接口或者继承`Thread`类来完成的。一旦创建了线程,可以通过调用`start()`方法启动它,这将使得线程进入就绪...