Concurrent container JUC-AQS synchronization component (2)

CountDownLatch、Semaphore、CyclicBarrier、ReentrantLock、Condition、FutureTask

CountDownLatch

**Latching down counter down**
Synchronous blocking class, completes the function of blocking the current thread, given a counter, atomic operation, the counter cannot be reset.

1. Through a count to ensure whether the thread needs to be blocked. Realize the scenario where one or more threads wait for the execution of other threads.
CountDownLatch
2. The program needs to wait for a certain condition to complete before proceeding to the following operations (for example, when the parent task waits for all child tasks to be completed, then continue to proceed).

We define a CountDownLatch and initialize it with a given counter. The counter is an atomic operation , ensuring that only one thread operates the counter at the same time. The thread that calls the await method of this type will always be in a blocked state. Other threads call the countDown method (each time the counter is -1), when the counter becomes 0, all waiting threads will continue to execute.

final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
    final int threadNum = i;
    exec.execute(() -> {
        try {
            test(threadNum);  //需要被等待的线程执行的方法
        } catch (Exception e) {
            log.error("exception", e);
        } finally {
            countDownLatch.countDown();
        }
    });
}
countDownLatch.await();

3. Multiple threads complete a task, but the task only wants to give it a specified time. After this time (the counter has not been cleared), it will not continue to wait, and it will count as much as it is completed. (Not to destroy all threads at the first time, but to let the executing thread finish first). countDownLatch.await (waiting time length, time unit);

scenes to be used

The query needs to wait for a certain condition to complete before continuing to perform subsequent operations (Ex: parallel computing) split task

Semaphore

Monitor the number of concurrency to ensure that the number
of requests (the number of concurrent access control threads) at the same time, reaching the upper limit will block

Semaphore is a very important concept in the operating system. Semaphore in the Java concurrency library can easily complete the control of similar operating system semaphores. Semaphore can easily control the number of threads simultaneously accessed by a certain resource in the system.
In the data structure, we have learned about linked lists. Linked lists can normally store unlimited nodes, while Semaphore can implement linked lists of limited size .

scenes to be used

  1. Only resources with limited access can be provided. For example, the maximum number of connections to the database is 20, while the upper-level concurrency is far greater than 20. If there is no restriction, it can cause concurrency exceptions (connections cannot be obtained). When Semaphore is set to 1, it is very similar to single thread.
  2. Concurrency is very high. If you want to exceed the allowed number of concurrency, discard it.
/**
 * 1、普通调用
 */
try {
     semaphore.acquire(); // 获取一个许可
     test();//需要并发控制的内容
     semaphore.release(); // 释放一个许可
} catch (Exception e) {
     log.error("exception", e);
}

/**
 * 2、acquire(n),release(n)
 * 同时获取多个许可,同时释放多个许可
 */
 try {
     semaphore.acquire(2);
     test();
     semaphore.release(2);
} catch (Exception e) {
     log.error("exception", e);
}

//tryAcquire()
//tryAcquire(int permits)//permits尝试获取许可的次数
//tryAcquire(long timeout, TimeUnit unit);
//tryAcquire(int permits,long timeout, TimeUnit unit)
/*
 * 3、tryAcquire())//尝试获取一个许可
 * 尝试获取许可,获取不到不执行
 */
 try {
     if (semaphore.tryAcquire()) {
        test(threadNum);
        semaphore.release();
     }
 } catch (Exception e) {
     log.error("exception", e);
}
/*
 * 4、尝试获取许可的时候等待一段时间,获取不到不执行
 * 参数1:等待时间长度  参数2:等待时间单位
 */
try {
     if (semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS)) {
        test(threadNum);
        semaphore.release(); 
     }
} catch (Exception e) {
     log.error("exception", e);
}

CyclicBarrier

Synchronization auxiliary class , run a group of threads to wait to a common barrier point, realize that multiple threads wait for each other, all threads are ready to continue execution, realized by counters.

When a thread calls await(), it enters the awaiting waiting state and sets the counter to -1 until all threads call await() to make the counter 0, and the threads continue to execute at the same time.

Since the counter can be reused after it is released (reset method), it is called a loop barrier .
CyclicBarrier

scenes to be used

Multi-threaded calculation of data, and finally combined calculation results.
For example, Excel saves the user's bank flow, and each page saves a user's bank flow for the past year. Now the user's daily average bank flow is counted, and the bank flow in each page is processed by multi-threading. After all are executed, the average daily bank turnover of each page will be obtained. Then, through the action of CyclicBarrier, the calculation results of these threads are used to calculate the daily average flow of the entire Excel.

//公共线程循环调用方法
private static CyclicBarrier barrier = new CyclicBarrier(5);

public static void main(String[] args) throws Exception {
    ExecutorService executor = Executors.newCachedThreadPool();
    for (int i = 0; i < 10; i++) {
        final int threadNum = i;
        Thread.sleep(1000);
        executor.execute(() -> {
            try {
                race(threadNum);
            } catch (Exception e) {
                log.error("exception", e);
            }
        });
    }
    executor.shutdown();
}

//使用方法1:每个线程都持续等待
private static void race(int threadNum) throws Exception {
    Thread.sleep(1000);
    log.info("{} is ready", threadNum);
    barrier.await();
    log.info("{} continue", threadNum);
}

//使用方法2:每个线程只等待一段时间
private static void race(int threadNum) throws Exception {
    Thread.sleep(1000);
    try {
        barrier.await(2000, TimeUnit.MILLISECONDS);
    } catch (InterruptedException | BrokenBarrierException | TimeoutException e) {
        log.warn("BarrierException", e);
    }
}

//使用方法3:在初始化的时候设置runnable,当线程达到屏障时优先执行runnable
private static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
    log.info("callback is running");
});

Comparison of CyclicBarrier and CountDownLatch

CyclicBarrier CountDownLatch
Reusable reset() Can only be used once
Multiple threads waiting for each other (internal relationship) The relationship of one or n threads waiting for other threads

CyclicBarrier provides methods to get the number of blocked threads and know whether the blocked threads are interrupted

Guess you like

Origin blog.csdn.net/eluanshi12/article/details/85259453