Article Directory
Preface
And then java.util.concurrent
the 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:
[发现:]
Use
await()
, after letting other threads finish executing, it will continue to wait, a bit similarthread 中的 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:
CyclicBarrier addition counter
As mentioned above 减法计数器
, so there must be 加法计数器
. Its operation is CyclicBarrier
based: .
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:
[发现:]
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 itcyclicBarrier.await()
, which is equivalent to adding it to the monitoring list.
3, when the set volume is occupied completely, it will triggerCyclicBarrier(int parties, Runnable barrierAction)
theRunnable
.
View await()
the execution logic of the source code :
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:
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: