首先介绍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() +
"进入,当前已有" + (3­sp.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() +
"已离开,当前已有" + (3­sp.availablePermits()) + "个并发");
}
}
}
}
输出结果
线程pool­1­thread­3进入,当前已有3个并发
线程pool­1­thread­2进入,当前已有3个并发
线程pool­1­thread­1进入,当前已有3个并发
线程pool­1­thread­2即将离开
线程pool­1­thread­2已离开,当前已有2个并发
线程pool­1­thread­5进入,当前已有3个并发
线程pool­1­thread­1即将离开
线程pool­1­thread­1已离开,当前已有2个并发
线程pool­1­thread­4进入,当前已有3个并发
线程pool­1­thread­4即将离开
线程pool­1­thread­4已离开,当前已有2个并发
线程pool­1­thread­8进入,当前已有3个并发
线程pool­1­thread­3即将离开
线程pool­1­thread­7进入,当前已有3个并发
线程pool­1­thread­3已离开,当前已有3个并发
线程pool­1­thread­8即将离开
线程pool­1­thread­8已离开,当前已有2个并发
线程pool­1­thread­9进入,当前已有3个并发
线程pool­1­thread­7即将离开
线程pool­1­thread­7已离开,当前已有2个并发
线程pool­1­thread­6进入,当前已有3个并发
线程pool­1­thread­9即将离开
线程pool­1­thread­9已离开,当前已有2个并发
线程pool­1­thread­10进入,当前已有3个并发
线程pool­1­thread­5即将离开
线程pool­1­thread­5已离开,当前已有2个并发
线程pool­1­thread­6即将离开
线程pool­1­thread­6已离开,当前已有1个并发
线程pool­1­thread­10即将离开
线程pool­1­thread­10已离开,当前已有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小时内删除。