Detailed Explanation of the Use of CountDownLatch and Thread Pool in java Parallel Package

  • 2021-08-21 20:22:45
  • OfStack

1.CountDownLatch

In this Huawei Cloud TaurusDB competition, I refer to the codes of two big brothers who participated in Ali's PolarDB competition before, and find that CountDownLatch is useful. I also read the code before, but I didn't understand it very well, so I can't write it myself. I will learn it first.

Literal understanding: CountDownLatch: reduced number of door bolts.

Create such a door bolt


CountDownLatch countDownLatch = new CountDownLatch(count);

Parameter: count, counting times of door bolt.

Calling countDownLatch. await () blocks the main thread until all threads have finished executing.

Whenever a thread executes a specified action, count will be reduced by 1. When count is equal to 0, the main thread will no longer block, and the following code will continue to be executed. When count is greater than 0, the main thread 1 will block directly, waiting for count to become 0. After each thread action is executed, countDownLatch. countDown () is executed, and the count of this doorbolt is minus 1.


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(" What Threads Should Do ");
  while(n < 10){
   n++;
  }
  countDownLatch.countDown();
 }).start();
}
try{
 countDownLatch.await();
}catch(InterruptedException e){
 logger.infor("InterruptedException!!");
}

2. Thread pool

In fact, the thread pool before the ipv6 project used, but also forget about the same, review 1.

Threads take time to create and close. If one thread is created for every small task, it may take more time to create and destroy the thread than the actual work of the thread, which will not be worth the candle. In addition to time, space also needs to be considered. Threads themselves also occupy memory space. A large number of threads will consume too much memory resources, which may cause OOM. In addition, when recycling, a large number of threads will prolong the pause time of GC.

Therefore, using threads in production environment must be controlled and managed

After using the thread pool, creating threads becomes getting free threads from the thread pool, and closing threads becomes returning threads to the thread pool.

One thread pool can be created through ThreadPoolExecutor, and ThreadPoolExecutor implements Executors interface.

Take chestnuts:


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;
   } 
  });
 }
}

This creates a thread pool. Parameters are interpreted in turn:

corePoolSize: Specifies the number of threads in the thread pool, which can have 10 surviving threads

maximumPoolSize: Specifies the maximum number of threads in the thread pool, with a maximum of 20 surviving threads in the thread pool

keepAliveTime: When the number of threads in the pool exceeds corePoolSize, how long will these threads be destroyed, 60s

unit: Unit of keepAliveTime

workQueue: Task queue, where tasks submitted but not executed exist. He is an BlockingQueue < Runnable > The object of the interface.

threadFactory: Thread factory, what kind of threads do you want to create

Focus on workQueue under 1:

According to the functional classification of queues, the following BlockingQueue interfaces can be used

Supplement: Use scenarios of CountDownLatch, CyclicBarrier and Semaphore in Java

Java concurrent package provides many useful tool classes to help developers with concurrent programming. Today, I will talk about the usage and usage scenarios of CountDownLatch, CyclicBarrier and Semaphore.

1. CountDownLatch usage scenarios and usage

CountDownLatch1 is typically used for a thread to wait for other threads to finish before it executes. For example, 1 family is waiting for Mom and Dad to come home before having a dinner. The example code is as follows:


public class CountDownLatchTest {
 
 public static void main(String[] args) throws Exception {
  final CountDownLatch cdl = new CountDownLatch(2);
  new Thread(){
   public void run() {
    try {
     System.out.println(" Waiting for Dad to come home ...");
     Thread.sleep(5000);
     cdl.countDown();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    
   };
  }.start();
  
  new Thread(){
   public void run() {
    try {
     System.out.println(" Waiting for Mom to come home ...");
     Thread.sleep(5000);
     cdl.countDown();
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   };
  }.start();
  
  cdl.await();
  System.out.println(" Mom and Dad are back ...");
  System.out.println(" The dinner party has begun ...");
 }
 
}

2. CyclicBarrier (fence) usage scenarios and usage

CyclicBarrier1 is like a group of threads waiting until a certain state, and then these groups of threads can execute at the same time (it feels a bit similar to CountDownLatch, but it is still different when you think about it, and it feels confusing).

The code example is as follows:


public class CyclicBarrierTest {
 
 public static void main(String[] args) {
  int count = 3;
  CyclicBarrier cb = new CyclicBarrier(count, new Runnable() {
   @Override
   public void run() {
    // Where all threads call the await After the method, it will go here 
    System.out.println(" Called after all thread operations are completed await Method ");
   }
  });
  
  for(int i=0;i<count;i++){
   new WriteLogHandler(cb).start();
  }
 }
 
 static class WriteLogHandler extends Thread{
  
  private CyclicBarrier cb = null;
  
  public WriteLogHandler(CyclicBarrier cb) {
   this.cb = cb;
  }
  
  @Override
  public void run() {
   try {
    System.out.println(" Threads: " + Thread.currentThread().getName() + " Start writing a journal ");
    Thread.sleep(2000);
    System.out.println(" Threads: " + Thread.currentThread().getName() + " Log writing ends, waiting for other threads ");
    cb.await();
    
    System.out.println(" All threads write log data and continue other operations ");
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
 }
 
}

3. Semaphore (Semaphore) usage scenarios and usage


Semaphore Similar to the use of locks to control access to a resource, the example code is as follows: 
public class SemaphoreTest {
 
 public static void main(String[] args) {
  ExecutorService executor = Executors.newCachedThreadPool();
  final Semaphore semaphore = new Semaphore(5);
  
  for(int i=0;i<10;i++){
   final int num = i;
   executor.execute(new Runnable() {
    @Override
    public void run() {
     try {
      semaphore.acquire();
      System.out.println(" Performing a mission " + num);
      Thread.sleep((long)Math.random() * 1000);
      System.out.println(" Mission " + num + " End of execution ");
      semaphore.release();
     } catch (Exception e) {
      e.printStackTrace();
     }
    }
   });
  }
  executor.shutdown();
 }
 
}

Related articles: