使用多线程容易碰到这样的问题,主线程需要等待各个任务线程完成后再继续(如释放资源等)。
常见的方法是在线程中使用计数器记录完成的线程数量,并且需要另外的一个线程轮询判断是否已经全部完成。
方案一:
final AtomicInteger counter = new AtomicInteger();
public void testRun() {
final int threadNum = 10;
// 开启任务线程
for (int i = 0; i < threadNum; i++) {
new Thread(new WorkRunnable()).start();
}
// 开启一个监听线程等待所有工作线程运行完毕
new Thread(new Runnable() {
public void run() {
while (true) {
if (counter.get() == threadNum) {
log.info("all threads finish");
break;
}
else {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
class WorkRunnable implements Runnable {
public void run() {
Random random = new Random();
int interval = random.nextInt(10 * 1000);
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(Thread.currentThread().getName() + " finish");
counter.incrementAndGet();
}
}
代码比较繁琐,监听线程等待100毫秒不会占用过多CPU资源。
另外可以使用线程池来解决,运用JDK1.5的线程池新特性。
方案二:
public void testRun() {
int threadNum = 10;
ExecutorService executor = Executors.newFixedThreadPool(threadNum);
// 开启任务线程
for (int i = 0; i < threadNum; i++) {
executor.execute(new WorkRunnable());
}
// 阻塞直到全部完成后关闭
while(!executor.isTerminated()) {
executor.shutdown();
}
log.info("all threads finish");
}
class WorkRunnable implements Runnable {
public void run() {
Random random = new Random();
int interval = random.nextInt(10 * 1000);
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(Thread.currentThread().getName() + " finish");
}
}
代码非常简洁,但是CPU占用很厉害