java常用同步工具类

来源:互联网 发布:郑云灿的淘宝店 编辑:程序博客网 时间:2024/05/22 17:04

阻塞队列:

BlockingQueue接口定义了可阻塞的put和take方法,同时也提供了非阻塞式的offer和poll方法。如果队列已满,那么put方法将阻塞直到有空间可用,如果队列为空那么take方法将会阻塞直到队列中有元素可以使用。而offer以及poll两个方法当队列已满或者队列为空而存储失败的时候,返回false。因此阻塞队列是利用队列的存储状态来控制线程的执行状态。

可以利用阻塞队列使用生产者——消费者模式,生产者把数据放入队列,而消费者从队列中读取数据,生产者不需要知道消费者的状态和数量,消费者同样不需要知道生产者是谁,只是从队列中读取数据进行使用。


  package com.pingan.home.demo;import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingDeque;public class BlockQueueShow {static BlockingQueue<Integer> blockingQueue = new LinkedBlockingDeque<Integer>();;public static void main(String[] args) {Thread product = new Thread(new BlockQueueCreate());Thread consumer = new Thread(new BlockQueueConsumer());product.start();consumer.start();}}class BlockQueueCreate implements Runnable {@Overridepublic void run() {try {for (int i = 0; i < 10; i++) {BlockQueueShow.blockingQueue.put(i);Thread.sleep(1000);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}class BlockQueueConsumer implements Runnable {@Overridepublic void run() {try {while (true) {System.out.println("Take:"+BlockQueueShow.blockingQueue.take());}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}


闭锁

闭锁可以延迟线程的进度直到其到达终止状态,闭锁相当于一扇门,初始状态为关闭的,没有任何线程可以通过,当满足一定的条件之后,闭锁这扇门会打开,允许所有的线程通过。闭锁可以确保某些任务知道其他的任务都完成之后才继续执行。
CountDownLatch是闭锁的一种实现,其状态包括一个计数器,该计数器在创建闭锁的时候被初始化为一个正整数,表示需要等待的事件数量。countDown方法用来改变闭锁的状态,调用一个闭锁的计数器就会递减,await方法会一直阻塞直到计数器变为0才开始执行。

 package com.pingan.home.demo;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CountDownLatchShow {/* 模拟了100米赛跑,10名选手已经准备就绪,只等裁判一声令下。当所有人都到达终点时,比赛结束。 */public static void main(String[] args) throws InterruptedException {ExecutorService runners = Executors.newFixedThreadPool(10);/* 十名选手 */for (int i = 0; i < 10; i++) {Runner runner=new Runner();runners.submit(runner);}/* begin减一,开始游戏 */CountDownLatchUtil.begin.countDown();long beginTime = System.nanoTime();/* 等待end变为0,即所有选手到达终点 */CountDownLatchUtil.end.await();long lastEndTime = System.nanoTime();System.out.println(lastEndTime - beginTime);runners.shutdown();}}class CountDownLatchUtil{/* 开始的倒数锁 */final static CountDownLatch begin = new CountDownLatch(1);/* 结束的倒数锁 */final static CountDownLatch end = new CountDownLatch(10);}class Runner implements Runnable {@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName()+ ":准备好");long everyoneStartTime = System.nanoTime();/** * 1.如果当前计数为零,则此方法立即返回,顺序执行下面代码。 * 2.等待(begin.countDown()代码后才会释放所有等待线程) */CountDownLatchUtil.begin.await();Thread.sleep((long) (Math.random() * 1000));long everyoneEndTime = System.nanoTime();System.out.println(Thread.currentThread().getName()+ ":跑完"+ (everyoneEndTime - everyoneStartTime));} catch (InterruptedException e) {e.printStackTrace();} finally {/* 每个选手到达终点时,end就减一 */CountDownLatchUtil.end.countDown();}}}

信号量

计数信号量(Counting Semaphore)用来控制同时访问某个特定资源的操作数量,或者同时执行某个指定操作的数量,计数信号量还可以用来实现某种资源池或者对容器施加边界。
Semaphore中管理者一组虚拟的许可,通过构造函数来进行初始化。在执行操作的时候可以首先获得许可(r如果还有剩余的许可),并在使用后释放许可,如果没有许可那么acquire方法将阻塞直到有许可。release方法将返回一个许可信号量。因此我们可用使用Semaphore将任何容器变成有界的阻塞容器。

package com.pingan.home.demo;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;public class SemaphoreShow {public static void main(String[] args) {// 线程池ExecutorService exec = Executors.newCachedThreadPool();// 只能5个线程同时访问final Semaphore semp = new Semaphore(5);// 模拟20个客户端访问for (int index = 0; index < 20; index++) {final int NO = index;Runnable run = new Runnable() {public void run() {try {// 获取许可semp.acquire();System.out.println("Accessing: " + NO);Thread.sleep((long) (Math.random() * 10000));// 访问完后,释放 ,如果屏蔽下面的语句,则在控制台只能打印5条记录,之后线程一直阻塞semp.release();} catch (InterruptedException e) {}}};exec.execute(run);}// 退出线程池exec.shutdown();}}


0 0
原创粉丝点击