Auxiliary tools under the JUC

Preface

And then java.util.concurrentthe package, there are several auxiliary tools operation. Such as CountDownLatch 减法计数器, CyclicBarrier 加法计数器and Semaphore 信号量.

I was stunned when I heard about these categories. Now let's talk about how to use these three tool categories.

CountDownLatch down counter

Given the initial size and capacity, it is called every time a thread performs an operation, and the capacity is -1. When
there is no data in it, it will continue to perform other operations.

Look at the following chestnuts:

import java.util.concurrent.CountDownLatch;

/**
 * 减法  计数器;用于 必须保证所有线程都执行完后继续其他操作。
 */
public class CountDownTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 1、计数器对象的创建,并给定计数器初始大小数
        CountDownLatch countDownLatch = new CountDownLatch(6);

        // 开启多个线程执行操作
        for (int i = 1; i <= 6; i++) {
    
    
            new Thread(()->{
    
    
                System.out.println(Thread.currentThread().getName()+" get ticket");
                // 2、每个线程执行某项操作时,将计数器-1
                countDownLatch.countDown();
            },String.valueOf(i)).start();
        }

        // 3、等待计数器中的数据门票消耗完
        countDownLatch.await();
        // 4、打印信息
        System.out.println("ticket num 0");
    }
}

The execution result is as follows:
Insert picture description here
[发现:]

Use await(), after letting other threads finish executing, it will continue to wait, a bit similar thread 中的 join(), wait for all threads to finish executing before continuing other operations below.

Check the jdk 1.8 development manual, which explains the method as follows:
Insert picture description here

CyclicBarrier addition counter

As mentioned above 减法计数器, so there must be 加法计数器. Its operation is CyclicBarrierbased: .
Look at the following example:

package demo5_1;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 加法计数器
 */
public class CyclicBarrierDemo {
    
    
    public static void main(String[] args) {
    
    
        // 创建 10个 大小的  计数器
        //CyclicBarrier cyclicBarrier = new CyclicBarrier(10);
        CyclicBarrier cyclicBarrier = new CyclicBarrier(10,()->{
    
    
            System.out.println("票售完");
        });

        // 创建多线程
        for (int i = 1; i <= 10 ; i++) {
    
    
            new Thread(()->{
    
    
                // 打印信息
                System.out.println(Thread.currentThread().getName()+" get ticket");
                // 计数器等待
                try {
    
    
                    cyclicBarrier.await();
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
    
    
                    e.printStackTrace();
                }
            },String.valueOf(i)).start();
        }
    }
}

The log print information after running is as follows:
Insert picture description here
[发现:]

1. An addition counter is defined at the beginning, and the construction method adopted is as follows public CyclicBarrier(int parties, Runnable barrierAction).
2. After each thread executes some business, call it cyclicBarrier.await(), which is equivalent to adding it to the monitoring list.
3, when the set volume is occupied completely, it will trigger CyclicBarrier(int parties, Runnable barrierAction)the Runnable.

View await()the execution logic of the source code :
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here

Semaphore

The semaphore tool class is generally used for limited resource classes. In
multi-threaded processing, if a limited number of threads are fully occupied, only unoccupied threads are allowed to wait;
when the initially occupied thread is released, subsequent threads In order to be used.

Similar to the following logic:

Created with Raphaël 2.2.0 线程进入 开始获取座位 座位被占用? 拿到座位 yes no

It's 令牌桶very similar to algorithm logic. such as请求限流!

The process of viewing the picture is still very abstract, look at the following chestnuts:

package demo5_1;

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * 信号量:用于某资源占用,其他处理等待其他线程处理完后才能处理
 */
public class SemphoreDemo {
    
    
    public static void main(String[] args) {
    
    
        // 假设 座位只有3个
        Semaphore semaphore = new Semaphore(3);
        // 创建线程
        for (int i = 1; i <= 12 ; i++) {
    
    
            new Thread(()->{
    
    
                try {
    
    
                    // 获取座位(此处会造成阻塞   必须等待有空位才会分配,即向下执行)
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+" 获取座位");
                    // 假设拿到座位后占用2秒
                    TimeUnit.SECONDS.sleep(2);
                    // 离开座位 原则上应该放在finally中执行 --- 释放资源操作
                    //semaphore.release();
                    //System.err.println(Thread.currentThread().getName()+" 离开座位");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }finally {
    
    
                    // 离开座位 原则上应该放在finally中执行--- 释放资源操作
                    semaphore.release();
                    // 用err只是颜色区分日志打印
                    System.err.println(Thread.currentThread().getName()+" 离开座位");
                }

            },String.valueOf(i)).start();
        }
    }
}

The console output log after execution is as follows:
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_38322527/article/details/114937513