java并发包中CountDownLatch和线程池的使用

2022-06-14 10:48:29

1.CountDownLatch

现在做的这个华为云TaurusDB比赛中,参考的之前参加过阿里的PolarDB大赛的两个大佬的代码,发现都有用到CountDownLatch这个类,之前看代码的时候也看过,但是没有搞得很明白,自己写也写不出来,在此自己先学习一下。

字面理解:CountDownLatch:数量减少的门栓。

创建这样一个门栓

CountDownLatch countDownLatch = new CountDownLatch(count);

参数:count,门栓的计数次数。在所有线程执行完成之前,调用countDownLatch.await()阻塞主线程。每当一个线程执行完一个指定动作之后,count就会减少1,当count等于0时,主线程不再阻塞,开始继续执行下面的代码,当count大于0时,主线程一直阻塞,等待count变为0。每个线程动作执行结束后,执行countDownLatch.countDown(),这个门栓的count减一。

int ThreadNum = 16;
CountDownLatch countDownLatch = new CountDownLatch(ThreadNum);
for(int i = 0; i < ThreadNum ; i++){
   final int finalI = i;
   new Thread(() -> {
      int n = 0;
      System.out.println("线程应该做的事情");
      while(n < 10){
         n++;
      }
      countDownLatch.countDown();
   }).start();
}
try{
   countDownLatch.await();
}catch(InterruptedException e){
   logger.infor("InterruptedException!!");
}

2.线程池

其实线程池之前的ipv6的项目里用过,但是也忘记得差不多了,复习一下。

 线程在创建和关闭时都需要花费时间,如果为每一个小的任务都创建一个线程,可能创建和销毁线程所用的时间会多于该线程真实工作所消耗的时间,就会得不偿失。除了时间,空间也需要考虑,线程本身也是要占用内存空间的,大量的线程会食用过多的内存资源,可能会造成OOM。另外在回收时,大量的线程会延长GC的停顿时间。

因此在生产环境中使用线程必须对其加以控制和管理

使用线程池之后,创建线程变成了从线程池中获得空闲的线程,关闭线程变成了归还线程给线程池。

通过ThreadPoolExecutor可以创建一个线程池,ThreadPoolExecutor实现了Executors接口。

举个栗子:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolTest {
    public static void main(String[] args) {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(10,20,60, 
                TimeUnit.SECOUNDS,new ArrayBlockingQueue<Runnable>(15000),new ThreadFactory(){
            private AtomicInteger threadId = new AtomicInteger(0);
            @Override
            public Thread newThread(Runnable r){
                Thread thread = new Thread(r);
                thread.setDaemon(true);
                String prefix = "thread-";
                thread.setName(prefix+threadId.incrementAndGet());
                return thread;
            }  
        });
    }
}

这样就创建了一个线程池。参数依次解释:

corePoolSize:指定了线程池中线程的数量,线程池中可以有10个存活的线程

maximumPoolSize:指定了线程池中最大的线程数,线程池中最多能有20个存活的线程

keepAliveTime:当线程池中的数量超过corePoolSize时,这些线程在多长时间会被销毁,60s

unit:keepAliveTime的单位

workQueue:任务队列,被提交但是没有被执行的任务存在的地方。他是一个BlockingQueue<Runnable>接口的对象。

threadFactory:线程工厂,你想创建什么样子的线程

重点说一下workQueue:

根据队列的功能分类,可以使用以下几种BlockingQueue接口

  • 作者:chen_yuxi
  • 原文链接:https://blog.csdn.net/chen_yuxi/article/details/97847857
    更新时间:2022-06-14 10:48:29