Java Semaphore 生产者消费者线程同步
来源:互联网 发布:大数据自学书籍推荐 编辑:程序博客网 时间:2024/05/30 23:27
一说到Java线程同步,首先想到的就是synchronized关键字,用来锁对象。实际上在Java的java.util.concurrent包中就给我们提供了很多关于同步的工具类。这里为大家介绍Semaphore这个类。这个类是干嘛用的呢?就好比信号标识,它把这十个房间的信息都标识到一个电子信息站牌中,这个信息牌管理所有的房间信息,当有空余的房间时,所有需要放物品的线程都会知道,并抢房间的授权资格,当放抢到授权资格的线程放入物品后,所有需取物品的线程就进入放入物品和抢授权资格的过程。具体代码如下,这个例子,实现了多个线程同时往一个容器中放物品,如果这个容器中的物品数大于10的时候,所有放入线程处于等待状态;还实现了多个线程同时往容器中取物品,当容器中物品为空时,取物线程等待。简单一句话描述:在不冲突的过程中从容器中多放,多取。
package thread.semaphore.two;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;import java.util.concurrent.TimeUnit;public class SemaphoreTest { public static void main(String[] args) { // 线程执行器 ExecutorService executor = Executors.newCachedThreadPool(); // 产生仓库 Warehouse warehouse = new Warehouse(); // 设置限额信号 Semaphore notFull = new Semaphore(10); // 设置非空信号 Semaphore notEmpty = new Semaphore(0); // 产生生产者 PutterRunnable putter1 = new PutterRunnable(warehouse, "put1", notFull, notEmpty); PutterRunnable putter2 = new PutterRunnable(warehouse, "put2", notFull, notEmpty); // 产生消费者 GetterRunnable getter1 = new GetterRunnable(warehouse, "get1", notFull, notEmpty); GetterRunnable getter2 = new GetterRunnable(warehouse, "get2", notFull, notEmpty); executor.execute(putter1); executor.execute(putter2); executor.execute(getter1); // 如果有需要,可以把这个方法放开,就可以实现多放多取。 // executor.execute(getter2); } // 数据存储仓库 static class Warehouse { // 库存容量 List<Object> list = new ArrayList<Object>(); // 核心锁(非冲突锁) Semaphore core = new Semaphore(1, true); public void put(Object obj, String threadName) { try { // 保证不冲突 core.acquire(); list.add(obj); // 判断在生产时,填充位的对象是否是已经有值的,如果有则表示程序错误 System.out.println("+++ " + threadName + " list.size = " + list.size() + ";放入的obj=" + obj); // 退出核心锁 core.release(); } catch (Exception e) { e.printStackTrace(); } finally { } } @SuppressWarnings("finally") public Object get(String threadName) { Object obj = null; try { // 保证不冲突 core.acquire(); obj = list.remove(0); // 判断在消费时,需要消费位置的对象是否是空的。,如果有则表示程序错误 System.out.println(" --- " + threadName + " list.size = " + list.size() + ";取出的obj=" + obj); // 退出核心锁 core.release(); } catch (Exception e) { e.printStackTrace(); } finally { return obj; } } } // putter线程, static class PutterRunnable implements Runnable { Warehouse warehouse; Random random; String rannableName; // 非满锁 Semaphore notFull; // 非空锁 Semaphore notEmpty; public PutterRunnable(Warehouse warehouse, String rannableName, Semaphore notFull, Semaphore notEmpty) { this.warehouse = warehouse; random = new Random(); this.rannableName = rannableName; this.notFull = notFull; this.notEmpty = notEmpty; } @Override public void run() { while (true) { try { // 获取存储限额的插入许可,如果达到限额,则等待插入许可,否则继续往下执行 notFull.acquire(); warehouse.put((Object) (random.nextInt() + ""), rannableName); // 插入成功后,则添加非空的授权许可。以供获取线程获取 notEmpty.release(); // TimeUnit.SECONDS.sleep(1); } catch (Exception e) { e.printStackTrace(); } } } } static class GetterRunnable implements Runnable { Warehouse warehouse; String rannableName; // 非空锁,当是0的时候进行阻塞 Semaphore notEmpty; // 非满锁 Semaphore notFull; public GetterRunnable(Warehouse warehouse, String rannableName, Semaphore notFull, Semaphore notEmpty) { this.warehouse = warehouse; this.rannableName = rannableName; this.notFull = notFull; this.notEmpty = notEmpty; } @Override public void run() { while (true) { try { // 获取非空授权许可,如果为空,则一直阻塞,等待插入线程插入后添加非空许可 notEmpty.acquire(); warehouse.get(rannableName); // 添加存储限额的插入许可,表示插入线程可以进行添加操作了 notFull.release(); TimeUnit.SECONDS.sleep(1); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }}
执行结果如下:
<div>+++ put1 list.size = 1;放入的obj=-2139723420+++ put2 list.size = 2;放入的obj=-1572405971+++ put1 list.size = 3;放入的obj=-1705274050 --- get1 list.size = 2;取出的obj=-2139723420+++ put2 list.size = 3;放入的obj=734422456+++ put1 list.size = 4;放入的obj=-1619127788+++ put2 list.size = 5;放入的obj=-1719033923+++ put1 list.size = 6;放入的obj=-122350698+++ put2 list.size = 7;放入的obj=2035853367+++ put1 list.size = 8;放入的obj=-538022868+++ put2 list.size = 9;放入的obj=-1842381319+++ put1 list.size = 10;放入的obj=-1810284972 --- get1 list.size = 9;取出的obj=-1572405971+++ put2 list.size = 10;放入的obj=-555471275 --- get1 list.size = 9;取出的obj=-1705274050+++ put1 list.size = 10;放入的obj=-1173490502 --- get1 list.size = 9;取出的obj=734422456+++ put2 list.size = 10;放入的obj=-313790792 --- get1 list.size = 9;取出的obj=-1619127788+++ put1 list.size = 10;放入的obj=-1067498081 --- get1 list.size = 9;取出的obj=-1719033923+++ put2 list.size = 10;放入的obj=-1634780208 --- get1 list.size = 9;取出的obj=-122350698+++ put1 list.size = 10;放入的obj=-1420550696 --- get1 list.size = 9;取出的obj=2035853367+++ put2 list.size = 10;放入的obj=2036388541 --- get1 list.size = 9;取出的obj=-538022868+++ put1 list.size = 10;放入的obj=-320507030 --- get1 list.size = 9;取出的obj=-1842381319+++ put2 list.size = 10;放入的obj=1682783427 --- get1 list.size = 9;取出的obj=-1810284972+++ put1 list.size = 10;放入的obj=243200254<div>
0 0
- Java Semaphore 生产者消费者线程同步
- 生产者、消费者 线程同步
- 线程同步--生产者消费者
- JAVA线程同步生产者/消费者简单例子
- [java线程同步]生产者消费者问题demo
- java线程(三) 生产者消费者模式-线程同步问题
- java线程 (一)生产者消费者模式-线程同步问题
- 线程同步之生产者消费者
- 线程同步生产者消费者问题
- 线程同步-生产者消费者问题
- 生产者消费者看线程同步
- 线程同步--生产者消费者模式
- java 线程生产者消费者
- Java线程间同步实现生产者-消费者模式
- java 线程同步问题之生产者消费者问题
- 经典线程同步问题(生产者&消费者)--Java实现
- Java 线程同步wait()用法 生产者 消费者问题
- Java经典线程同步问题------生产者与消费者
- 操作系统的概述
- 代码生成器 websocket即时通讯 shiro redis 后台框架源码
- 字符串变形词
- PHP:常用的方法
- 欢迎使用CSDN-markdown编辑器
- Java Semaphore 生产者消费者线程同步
- php的ldap安装问题汇总(linux)
- OSI参考模型
- JavaScript 运行机制详解:再谈Event Loop
- html拼接时,a标签的函数传参时,为什么要加引号?跟转义有无关系?(大家是怎么看到这篇博客的求告知,有什么疑问想说的欢迎评论)
- 把github上传的项目注册到bower
- DES加密解密工具
- java Socket基于TCP协议编程实现通信
- java---面向对象