java常用同步工具类
2016-04-18 13:55
471 查看
阻塞队列:
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 { @Override public 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 { @Override public 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 { @Override public 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(); } }
相关文章推荐
- java常用算法之返回目标数字在有序数组中的位置(假设有序数组中不存在重复数字)
- 深入理解 Java中的 流 (Stream)
- java判断字符串是否为空的方法总结
- Java8之默认方法和静态接口方法
- springMVC中from表单提交对象
- Java命名规范
- java NIO(转)
- JAVA锁机制
- java中四种操作(dom、sax、jdom、dom4j)xml方式详解与比较
- 在eclipse中使用javap
- java编程之SwingUtilities中invokeLater和invokeAndWait的使用
- 总结了一些java基本的一些陷阱
- Java 正则应用总结
- java基础(9)-- Java关键字及其作用
- myeclipse如何导出javadoc
- java常用算法之返回字符串中目标字符串的位置
- Eclipse ADT插件安装
- 搬圆桌-Java
- 在Android Eclipse 开发如何 使用 (*.aar)文件
- 深入浅出Java多线程