使用java线程池ExecutorService,执行多线程操作,使用CountDownLatch来保证多线程执行完毕之后,再释放线程池
新建一个类测试并发使用:
public class runDo {
private long id;
private String name;
private String env;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEnv() {
return env;
}
public void setEnv(String env) {
this.env = env;
}
}
新建测试类:设置不同的线程池 和 计数器 查看执行情况
public class TestRunnable {
static long num = 0;
public static void main(String args[]) {
System.out.println(getNum());
}
public static long getNum(){
int count = 20;
// 计数器 构造指定数量的CountDownLatch
CountDownLatch end = new CountDownLatch(count);
// 创建线程池,可设置最大并发数 超出的线程会 等待 其中一个执行完成
ExecutorService exec = Executors.newFixedThreadPool(10);
// 创建单一线程池,等于一个线程执行,顺序执行
//ExecutorService exec = Executors.newSingleThreadExecutor();
// 创建一个线程池,根据需要创建线程,线程执行完 可以继续复用
//ExecutorService exec = Executors.newCachedThreadPool();
List<runDo> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
runDo rundo = new runDo();
rundo.setId(i);
rundo.setName("name" + i);
rundo.setEnv("env" + i);
list.add(rundo);
}
for (runDo rundo : list) {
Runnable run = new MyRunnableTest(rundo, end);
//线程池一共10个线程, 多线程执行
exec.execute(run);
//返回 线程执行 耗时长 则 这里count 都为 20
//System.out.println("——计数器:"+ end.getCount());
}
try {
// 当前线程等待,直到计数器递减至零为止,除非该线程被中断
//end.await();
//当前线程等待,直到计数器到递减零为止,除非该线程被中断或经过了指定的等待时间
//总的计数器 大于 执行次数时候,需要设置超时 时间, 可以设置 时间单位
end.await(5, TimeUnit.SECONDS);
System.out.println("已经等待5s");
} catch (Exception e) {
e.printStackTrace();
}
// 关闭线程池 等待执行完成 ,不接受新任务
exec.shutdown();
return num ;
}
static class MyRunnableTest implements Runnable {
runDo rundo;
CountDownLatch end;
public MyRunnableTest(runDo rundo, CountDownLatch end) {
this.rundo = rundo;
this.end = end;
}
@Override
public void run() {
num = rundo.getId()+num;
try {
//Thread.sleep(3);
// System.out.println("可以查看newSingleThreadExecutor的情况下是否依此等待");
}catch (Exception e){
e.printStackTrace();
}
// end.toString():返回一个标识此锁存器及其状态的字符串
// end.getCount():返回当前计数 剩余的
System.out.println(Thread.currentThread().getName() +"——NUM:"+ num +"——"+ end.toString()+"——计数器:" +end.getCount());
// 减少锁存器的计数,如果计数达到零,则释放所有等待线程 ,如果到达零,则无影响
end.countDown();
}
}
}
当前测试控制台输出:
1、线程池 一共10个线程,NUM值最终为55,计数器没有到0等待5秒再继续执行
pool-1-thread-2——NUM:3——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 20]——计数器:20
pool-1-thread-4——NUM:10——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 20]——计数器:20
pool-1-thread-3——NUM:6——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 20]——计数器:20
pool-1-thread-1——NUM:3——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 20]——计数器:20
pool-1-thread-6——NUM:21——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 17]——计数器:17
pool-1-thread-5——NUM:15——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 20]——计数器:19
pool-1-thread-7——NUM:28——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 14]——计数器:14
pool-1-thread-8——NUM:36——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 13]——计数器:13
pool-1-thread-9——NUM:45——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 12]——计数器:12
pool-1-thread-10——NUM:55——java.util.concurrent.CountDownLatch@76f1ebbf[Count = 11]——计数器:11
已经等待5s
55
并发此时计数器不是依次减少的,将上面线程池改成
ExecutorService exec = Executors.newSingleThreadExecutor();
执行查看控制台输出:计数器依次减少
pool-1-thread-1——NUM:1——java.util.concurrent.CountDownLatch@a8f72d1[Count = 20]——计数器:20
pool-1-thread-1——NUM:3——java.util.concurrent.CountDownLatch@a8f72d1[Count = 19]——计数器:19
pool-1-thread-1——NUM:6——java.util.concurrent.CountDownLatch@a8f72d1[Count = 18]——计数器:18
pool-1-thread-1——NUM:10——java.util.concurrent.CountDownLatch@a8f72d1[Count = 17]——计数器:17
pool-1-thread-1——NUM:15——java.util.concurrent.CountDownLatch@a8f72d1[Count = 16]——计数器:16
pool-1-thread-1——NUM:21——java.util.concurrent.CountDownLatch@a8f72d1[Count = 15]——计数器:15
pool-1-thread-1——NUM:28——java.util.concurrent.CountDownLatch@a8f72d1[Count = 14]——计数器:14
pool-1-thread-1——NUM:36——java.util.concurrent.CountDownLatch@a8f72d1[Count = 13]——计数器:13
pool-1-thread-1——NUM:45——java.util.concurrent.CountDownLatch@a8f72d1[Count = 12]——计数器:12
pool-1-thread-1——NUM:55——java.util.concurrent.CountDownLatch@a8f72d1[Count = 11]——计数器:11
已经等待5s
55
Process finished with exit code 0
官方API:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CountDownLatch.html
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html