首先介绍Semaphore:一个计数信号量。用于控制同时访问资源的线程个数;
CyclicBarrier同步辅助类:从字面意思看是路障,这里用于线程之间的相互等待,到达某点后,继续向下执行。
CountDownLatch同步辅助类:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待,犹如倒计时计数器;
然后是Exchanger:实现两个对象之间数据交换,可阻塞队列ArrayBlockingQueue,通过阻塞队列间的通信来演示其作用;
最后介绍了几个同步集合。
计算机专业java+
1. Semaphore
Semaphore可以维护当前访问自身的线程个数,并提供了同步机制,使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。Semaphore 只对可用许可的号码进行计数,并采取相应的行动。
它具备两个主要方法:
acquire()
release()
计数信号量由一个指定数量的 "许可" 初始化。每调用一次 acquire(),一个许可会被调用线程取走。每调用一次 release(),一个许可会被返还给信号量。因此,在没有任何 release() 调用时,最多有 N 个线程能够通过 acquire() 方法,N 是该信号量初始化时的许可的指定数量。这些许可只是一个简单的计数器。
Semaphore实现的功能就像:银行办理业务,一共有5个窗口,但一共有10个客户,一次性最多有5个客户可以进行办理,其他的人必须等候,当5个客户中的任何一个离开后,在等待的客户中有一个人可以进行业务办理。
Semaphore提供了两种规则:
一种是公平的:获得资源的先后,按照排队的先后。在构造函数中设置true实现
一种是野蛮的:谁有本事抢到资源,谁就可以获得资源的使用权。
与传统的互斥锁的异同:
单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁“,再由另外一个线程释放”锁“,这可以应用于死锁恢复的一些场合。
应用场景:共享资源的争夺,例如游戏中选手进入房间的情况。
import urrent.ExecutorService;
import urrent.Executors;
import urrent.Semaphore;
public class SemaphoreTest {
public static void main(String[] args) {
//创建一个可根据需要创建新线程的线程池
ExecutorService service = wCachedThreadPool();
final Semaphore sp = new Semaphore(3);
//创建10个线程
for(int i=0;i<10;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
sp.acquire(); //获取灯,即许可权
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" +
Thread.currentThread().getName() +
"进入,当前已有" + (3sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" +
Thread.currentThread().getName() +
"即将离开");
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" +
Thread.currentThread().getName() +
"已离开,当前已有" + (3sp.availablePermits()) + "个并发");
}
};
}
}
}
输出结果
线程pool1thread3进入,当前已有3个并发
线程pool1thread2进入,当前已有3个并发
线程pool1thread1进入,当前已有3个并发
线程pool1thread2即将离开
线程pool1thread2已离开,当前已有2个并发
线程pool1thread5进入,当前已有3个并发
线程pool1thread1即将离开
线程pool1thread1已离开,当前已有2个并发
线程pool1thread4进入,当前已有3个并发
线程pool1thread4即将离开
线程pool1thread4已离开,当前已有2个并发
线程pool1thread8进入,当前已有3个并发
线程pool1thread3即将离开
线程pool1thread7进入,当前已有3个并发
线程pool1thread3已离开,当前已有3个并发
线程pool1thread8即将离开
线程pool1thread8已离开,当前已有2个并发
线程pool1thread9进入,当前已有3个并发
线程pool1thread7即将离开
线程pool1thread7已离开,当前已有2个并发
线程pool1thread6进入,当前已有3个并发
线程pool1thread9即将离开
线程pool1thread9已离开,当前已有2个并发
线程pool1thread10进入,当前已有3个并发
线程pool1thread5即将离开
线程pool1thread5已离开,当前已有2个并发
线程pool1thread6即将离开
线程pool1thread6已离开,当前已有1个并发
线程pool1thread10即将离开
线程pool1thread10已离开,当前已有0个并发2. CyclicBarrier
一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point)。在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待,此时 CyclicBarrier 很有用。因为该
barrier 在释放等待线程后可以重用,所以称它为循环 的 barrier。
CyclicBarrier 支持一个可选的 Runnable 命令,在一组线程中的最后一个线程到达之后(但在释放所有线程之前),该命令只在每个屏障点运行一次。若在继续所有参与线程之前更新共享状态,此屏障操作很有用。
eg:3个线程到达某个集合点后再向下执行,可使用await方法实现;
import urrent.CyclicBarrier;
import urrent.ExecutorService;
import urrent.Executors;
public class CyclicBarrierTest {
public static void main(String[] args) {
ExecutorService service = wCachedThreadPool();
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论