(一)并发包中的(计数器)CountDownLatch,(屏障)CyclicBarrier,(计数信号量)Semaphore
(计数器)CountDownLatch
CountDownLatch 类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
代码实战:
首先写了一个枚举类,便于下面的举例
package com.bestqiang.thread.JUC;
/** * @author BestQiang */
public enum SeasonEnum {
spring(1,"春"),summer(2,"夏"),autumn(3,"秋"),winter(4,"冬");
private Integer index;
private String season;
SeasonEnum(Integer index, String season) {
this.index = index;
this.season = season;
}
public static SeasonEnum forEach_SeasonEnum(int index) {
SeasonEnum[] values = SeasonEnum.values();
for (SeasonEnum value : values) {
if(index == value.index) {
return value;
}
}
return null;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
public String getSeason() {
return season;
}
public void setSeason(String season) {
this.season = season;
}
}
CountDownLatch的实战:
package com.bestqiang.thread.JUC;
import java.util.concurrent.CountDownLatch;
/** * @author BestQiang */
public class CountDownLatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(4);
for(int i = 1; i <= 4; i ++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 天,来了");
countDownLatch.countDown();
}, SeasonEnum.forEach_SeasonEnum(i).getSeason()).start();
}
countDownLatch.await();
// 等到倒计时为0的时候,开始执行下面的语句
System.out.println("朱自清的脚步近了!");
}
}
运行结果:
"C:\Program Files\java\jdk1.8.0_101\bin\java.exe" -javaagent:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\lib\idea_rt.jar=54728:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\java\jdk1.8.0_101\jre\lib\charsets.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\deploy.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\access-bridge-64.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\cldrdata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\dnsns.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jaccess.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jfxrt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\localedata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\nashorn.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunec.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunjce_provider.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunmscapi.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunpkcs11.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\zipfs.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\javaws.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jce.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfr.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfxswt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jsse.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\management-agent.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\plugin.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\resources.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\rt.jar;D:\workspace_idea\multithreading\out\production\threadPools" com.bestqiang.thread.JUC.CountDownLatchDemo
夏 天,来了
冬 天,来了
春 天,来了
秋 天,来了
朱自清的脚步近了!
(屏障)CyclicBarrier
CyclicBarrier 初始化时规定一个数目,然后计算调用了CyclicBarrier.await() 进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。
CyclicBarrier 就象它名字的意思一样,可看成是个障碍, 所有的线程必须到齐后才能一起通过这个障碍。
CyclicBarrier 初始时还可带一个Runnable 的参数, 此Runnable 任务在CyclicBarrier 的数目达到后,所有其它线程被唤醒前被执行。
代码实战:
package com.bestqiang.thread.JUC;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/** * @author BestQiang */
public class CyclicBarrierDemo {
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
// 等到CyclicBarrier.await()的线程数达到7的时候,开始执行下面的语句
System.out.println( "开始召唤神龙!");
});
for(int i = 1; i <= 7; i ++) {
int f = i;
int r = new Random().nextInt(4);
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "\t 收集到第:" + f + "龙珠");
try {
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}, SeasonEnum.forEach_SeasonEnum(r == 0 ? 1 : r).getSeason()).start();
}
}
}
"C:\Program Files\java\jdk1.8.0_101\bin\java.exe" -javaagent:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\lib\idea_rt.jar=55089:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\java\jdk1.8.0_101\jre\lib\charsets.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\deploy.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\access-bridge-64.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\cldrdata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\dnsns.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jaccess.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jfxrt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\localedata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\nashorn.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunec.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunjce_provider.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunmscapi.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunpkcs11.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\zipfs.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\javaws.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jce.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfr.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfxswt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jsse.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\management-agent.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\plugin.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\resources.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\rt.jar;D:\workspace_idea\multithreading\out\production\threadPools" com.bestqiang.thread.JUC.CyclicBarrierDemo
春 收集到第:1龙珠
夏 收集到第:3龙珠
春 收集到第:2龙珠
春 收集到第:4龙珠
秋 收集到第:5龙珠
夏 收集到第:6龙珠
春 收集到第:7龙珠
开始召唤神龙!
Process finished with exit code 0
(计数信号量)Semaphore
Semaphore 是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore 可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下:
availablePermits函数用来获取当前可用的资源数量
semaphore.acquire(); //申请资源
semaphore.release();// 释放资源
package com.bestqiang.thread.JUC;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
/** * @author BestQiang * 抢车位 */
public class SemaphoreDemo {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);// 模拟三个车位
for( int i = 1; i <= 7; i++) { // 模拟6部汽车
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + "\t 抢到车位");
TimeUnit.SECONDS.sleep(3);
System.out.println("\t" + "停车3秒后离开车位");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();
}
}, String.valueOf(i)).start();
}
}
}
"C:\Program Files\java\jdk1.8.0_101\bin\java.exe" -javaagent:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\lib\idea_rt.jar=55756:D:\JetBrains\apps\IDEA-U\ch-0\191.6707.61\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\java\jdk1.8.0_101\jre\lib\charsets.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\deploy.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\access-bridge-64.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\cldrdata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\dnsns.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jaccess.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\jfxrt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\localedata.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\nashorn.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunec.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunjce_provider.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunmscapi.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\sunpkcs11.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\ext\zipfs.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\javaws.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jce.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfr.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jfxswt.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\jsse.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\management-agent.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\plugin.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\resources.jar;C:\Program Files\java\jdk1.8.0_101\jre\lib\rt.jar;D:\workspace_idea\multithreading\out\production\threadPools" com.bestqiang.thread.JUC.SemaphoreDemo
1 抢到车位
4 抢到车位
2 抢到车位
停车3秒后离开车位
停车3秒后离开车位
停车3秒后离开车位
5 抢到车位
3 抢到车位
6 抢到车位
停车3秒后离开车位
停车3秒后离开车位
7 抢到车位
停车3秒后离开车位
停车3秒后离开车位
Process finished with exit code 0
小总结:CountDownLatch为倒计数,CyclicBarrier为正计数,Semaphore为抢车位。