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