Semaphore实现信号灯java
lSemaphore能够维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore能够控制同时访问资源的线程个数,例如,实现一个文件容许的并发访问数。并发
ØSemaphore实现的功能就相似厕全部5个坑,假若有十我的要上厕所,那么同时能有多少我的去上厕所呢?同时只能有5我的可以占用,当5我的中的任何一我的让开后,其中在等待的另外5我的中又有一个能够占用了。dom
Ø另外等待的5我的中能够是随机得到优先机会,也能够是按照先来后到的顺序得到机会,这取决于构造Semaphore对象时传入的参数选项。eclipse
l单个信号量的Semaphore对象能够实现互斥锁的功能,而且能够是由一个线程得到了“锁”,再由另外一个线程释放“锁”,这可应用于死锁恢复的一些场合。工具
管理停车位,一个小的电子设备,实时性强就要semaphore。 关于从这里开始的各个同步工具例子的代码,现场编写的效果还不如拷贝代码到eclipse中进行解释的效果直观和简洁,这样能一会儿把全局和总体展示在学员面前。而后再能够带着你们一行行地去写,这样能够起到巩固原理和锻炼你们编写代码能力和启发思考的效果。ui
管理停车位,一个小的电子设备,实时性强就要semaphore。
关于从这里开始的各个同步工具例子的代码,现场编写的效果还不如拷贝代码到eclipse中进行解释的效果直观和简洁,这样能一会儿把全局和总体展示在学员面前。而后再能够带着你们一行行地去写,这样能够起到巩固原理和锻炼你们编写代码能力和启发思考的效果。线程
public class SemaphoreTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Semaphore sp = new Semaphore(3); 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() + "即将离开"); sp.release(); //下面代码有时候执行不许确,由于其没有和上面的代码合成原子单元 System.out.println("线程" + Thread.currentThread().getName() + "已离开,当前已有" + (3-sp.availablePermits()) + "个并发"); } }; service.execute(runnable); } } }
CyclicBarrier
表示你们彼此等待,你们集合好后才开始出发,分散活动后又在指定地点集合碰面,这就比如整个公司的人员利用周末时间集体郊游同样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐,…。
CountDownLatch
犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减1,当计数到达0时,则全部等待者或单个等待者开始执行。这直接经过代码来讲明CountDownLatch的做用,这样学员的理解效果更直接。
能够实现一我的(也能够是多我的)等待其余全部人都来通知他,能够实现一我的通知多我的的效果,相似裁判一声口令,运动员同时开始奔跑,或者全部运动员都跑到终点后裁判才能够公布结果,用这个功能作百米赛跑的游戏程序不错哦!还能够实现一个计划须要多个领导都签字后才能继续向下实施的状况。
Exchanger
用于实现两我的之间的数据交换,每一个人在完成必定的事务后想与对方交换数据,第一个先拿出数据的人将一直等待第二我的拿着数据到来时,才能彼此交换数据。code
Cyclic:循环的,有周期性的
Barrier:障碍物,屏障
Latch:门闩,闩锁对象
讲解CyclicBarrier的功能时,经过辅助画图的方式说明,效果会更好。
\ /
\ | /
------------------------三个线程干完各自的任务,在不一样的时刻到达集合点后,就能够接着忙各自的工做去了,再到达新的集合点,再去忙各自的工做,
到达集合点了用CyclicBarrier对象的await方法表示。
/ | \
/ | \
-------------------
为何几我的能碰到一块儿,说白了,就是你们都把手头这一阶段的工做作完了,就能够碰到一块儿了。譬如,我下楼等方老师,就是等他手头工做作完了,他到达了要集合的状态,就集合了。游戏
-----------------CyclicBarrier的代码:--------------------------------- import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CyclicBarrierTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final CyclicBarrier cb = new CyclicBarrier(3); for(int i=0;i<3;i++){ Runnable runnable = new Runnable(){ public void run(){ try { Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); Thread.sleep((long)(Math.random()*10000)); System.out.println("线程" + Thread.currentThread().getName() + "即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候")); cb.await(); } catch (Exception e) { e.printStackTrace(); } } }; service.execute(runnable); } service.shutdown(); } }
-----------------CountdownLatch的代码:---------------------------------
package cn.itcast.day3.thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CountdownLatchTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("线程" + Thread.currentThread().getName() +
"正准备接受命令");
cdOrder.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"回应命令处理结果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将发布命令");
cdOrder.countDown();
System.out.println("线程" + Thread.currentThread().getName() +
"已发送命令,正在等待结果");
cdAnswer.await();
System.out.println("线程" + Thread.currentThread().getName() +
"已收到全部响应结果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}
exchange方法就至关于两手高高举着待交换物,等待人家前来交换,一旦人家到来(即人家也执行到exchange方法),则二者立马完成数据的交换。
import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExchangerTest { public static void main(String[] args) { ExecutorService service = Executors.newCachedThreadPool(); final Exchanger exchanger = new Exchanger(); service.execute(new Runnable(){ public void run() { try { String data1 = "zxx"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); service.execute(new Runnable(){ public void run() { try { String data1 = "lhm"; System.out.println("线程" + Thread.currentThread().getName() + "正在把数据" + data1 +"换出去"); Thread.sleep((long)(Math.random()*10000)); String data2 = (String)exchanger.exchange(data1); System.out.println("线程" + Thread.currentThread().getName() + "换回的数据为" + data2); }catch(Exception e){ } } }); } }