Java判断线程池线程是否执行完毕

网友投稿 360 2023-06-02

java判断线程池线程是否执行完毕

Java判断线程池线程是否执行完毕

在使用多线程的时候有时候我们会使用 java.util.concurrent.Executors的线程池,当多个线程异步执行的时候,我们往往不好判断是否线程池中所有的子线程都已经执行完毕,但有时候这种判断却很有用,例如我有个方法的功能是往一个文件异步地写入内容,我需要在所有的子线程写入完毕后在文件末尾写“---END---”及关闭文件流等,这个时候我就需要某个标志位可以告诉我是否线程池中所有的子线程都已经执行完毕,我使用这种方式来判断。

public class MySemaphore {

public static void main(String[] args) throws IOException, InterruptedException {

final File stream = new File("c:\\temp\\stonefeng\\stream.txt");

final OutputStream os = new FileOutputStream(stream);

final OutputStreamWriter writer = new OutputStreamWriter(os);

final Semaphore semaphore = new Semaphore(10);

ExecutorService exec = Executors.newCachedThreadPool();

final long start = System.currentTimeMillis();

for (int i = 0; i < 10000000; i++) {

final int num = i;

Runnable task = new Runnable() {

@Override

public void run() {

try {

semaphore.acquire();

writer.write(String.valueOf(num)+"\n");

semaphore.release();

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};

exec.submit(task);

}

exec.shutdown();

while(true){

if(exec.isTerminated()){

writer.write("---END---\n");

writer.close();

System.out.println("所有的子线程都结束了!");

break;

}

Thread.sleep(1000);

}

final long end = System.currentTimeMillis();

System.out.println((end-start)/1000);

}

}

当调用ExecutorService.shutdown方法的时候,线程池不再接收任何新任务,但此时线程池并不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。在调用shutdown方法后我们可以在一个死循环里面用isTerminated方法判断是否线程池中的所有线程已经执行完毕,如果子线程都结束了,我们就可以做关闭流等后续操作了。

判断线程池中的线程是否全部执行完毕的另外一种解决方案则是使用闭锁(CountDownLatch)来实现,CountDownLatch是一种灵活的闭锁实现,它可以使一个或多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化为一个正数,表示需要等待的事件数量。couhnRSfzVUntDown方法递减计数器,表示有一个事件已经发生了,而await方法等待计数器达到零,即表示需要等待的事情都已经发生。可以使用闭锁来这样设计程序达到目的:

public class CountDownLatchApproach {

public static void main(String[] args) throws IOException, InterruptedException {

final int nThreads = 10;

final CountDownLatch endGate = new CountDownLatch(nThreads);

final File stream = new File("c:\\temp\\stonefeng\\stream.txt");

final OutputStream os = new FileOutputStream(stream);

final OutputStreamWriter writer = new OutputStreamWriter(os);

ExecutorService exec = Executors.newCachedThreadPool();

for (int i = 0; i < nThreads; i++) {

final int num = i;

Runnable task = new Runnable() {

@Override

public void run() {

try {

writer.write(String.valueOf(num)+"\n");

} catch (IOException e) {

e.printStackTrace();

} finally {

endGate.countDown();

}

}

};

exec.submit(task);

}

endGate.await();

writer.write("---END---\n");

writer.close();

}

}

这种解决方案虽然可以达到目的但是性能差到没朋友,我更倾向于使用第一种方案hnRSfzVU。

现在我们有了更优雅的第三种方案,它的执行性能也不错。

public class MySemaphore {

public static void main(String[] args) throws IOException, InterruptedException {

final File stream = new File("c:\\temp\\stonefeng\\stream.txt");

final OutputStream os = new FileOutputStream(stream);

final OutputStreamWriter writer = new OutputStreamWriter(os);

final Semaphore semaphore = new Semaphore(10);

ExecutorService exec = Executors.newCachedThreadPool();

final long start = System.currentTimeMillis();

for (int i = 0; i < 10000000; i++) {

final int num = i;

Runnable task = new Runnable() {

@Override

public void run() {

try {

semaphore.acquire();

writer.write(String.valueOf(num)+"\n");

semaphore.release();

} catch (IOException e) {

e.printStackTrace();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

};

exec.submit(task);

}

exec.shutdown();

exec.awaitTermination(1, TimeUnit.HOURS);

writer.write("---END---\n");

writer.close();

System.out.println("ËÓеÄÓÏ̶߳¼½ÊøÁË£¡");

final long end = Syhttp://stem.currentTimeMillis();

System.out.println((end-start)/1000);

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:JavaApi实现更新删除及读取节点
下一篇:Java桥接模式原理及用法解析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~