Java判断线程池线程是否执行完毕
作者:斗战圣猿 发布时间:2023-10-18 12:09:29
在使用多线程的时候有时候我们会使用 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是一种灵活的闭锁实现,它可以使一个或多个线程等待一组事件发生。闭锁状态包括一个计数器,该计数器被初始化为一个正数,表示需要等待的事件数量。countDown方法递减计数器,表示有一个事件已经发生了,而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();
}
}
这种解决方案虽然可以达到目的但是性能差到没朋友,我更倾向于使用第一种方案。
现在我们有了更优雅的第三种方案,它的执行性能也不错。
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 = System.currentTimeMillis();
System.out.println((end-start)/1000);
}
}
来源:https://www.cnblogs.com/zhangpeng8888/p/12702251.html


猜你喜欢
- 1. Android.bp 文件是什么?Android.bp 文件首先是 Android 系统的一种编译配置文件,是用来代替原来
- 大部分Java开发者都在使用Map,特别是HashMap。HashMap是一种简单但强大的方式去存储和获取数据。但有多少开发者知道HashM
- 本文实例讲述了java实现的DES加密算法。分享给大家供大家参考,具体如下:一、DES加密算法介绍1、要求密钥必须是8个字节,即64bit长
- 简述Java中Socket分为普通Socket和NioSocket两种,这里介绍Socket。我们可以把Socket比作两个城市间的交通工具
- 1.什么是逆向工程mybaits需要程序员自己编写sql语句,mybatis官方提供逆向工程 可以针对单表自动生成mybatis执行所需要的
- 当前,JVM生态圈主要的三大构建工具:Apache Ant(带着Ivy)MavenGradle对于初学者,Ant是最清晰的,只要读懂Xml配
- 客户端代码using System;using System.Collections.Generic;using System.Compon
- 介绍:unity界面开发,会用到很多导航的按钮,他们是公共的,单击其中一个按钮,显示对应的界面。unity中,UGUI自带Toggle组件,
- 使用JPA CriteriaQuery查询的注意事项1.pojo类@Entity@Table(name = "report_wor
- 在C#2.0中,微软给我们带来了一些新的特性,例如泛型,匿名委托等。然而,这些新的特性多多少少会给人一种从别的语言中“抄”来的感觉(例如泛型
- 在很多场景中我们需要验证时间日期的是否属于正确的格式,验证时间是否符合常规的。1、验证 yyyy-MM-dd HH:mm:dd 格式的日期S
- 题目要求思路一:双指针(模拟)Javaclass Solution { public boolean isFlip
- 使用udp实现消息的接收和发送代码比较简单,但是别忘记关闭防火墙进行测试。首先便是服务端,使用Socket进行实现,参考代码如下: 
- 本文实例为大家分享了Java网络编程TCP实现文件上传的具体代码,供大家参考,具体内容如下上一篇博客,用网络编程TCP 实现聊天,这次实现文
- 目录引言SqlSessionFactory不使用 XML 构建 SqlSessionFactorySqlSessionFactoryBuil
- 前言 红包文化源远流长。从古时的红色纸包,到手
- 本文实例讲述了Android获取手机屏幕大小的方法。分享给大家供大家参考,具体如下:这里主要用了三个对象TextView ,Button ,
- 之前写轮播条或者指示器的时候都是UI图里面直接有,这样的效果并不好,给用户的体验比较差,所以闲暇之余自己写了个指示器,可以展现出一个优雅的效
- spring schedule 动态配置执行时间之前saas平台实现动态修改定时任务的时间,都是通过xx-job这样的框架来实现,这样我们可
- 什么是ByteBuddyByteBuddy是一个java的运行时代码生成库,他可以帮助你以字节码的方式动态修改java类的代码。为什么需要B