当前位置: 首页 > news >正文

Java并发案例04---生产者消费者问题03--使用ReentrantLock

/**
 * 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法,
 * 能够支持2个生产者线程以及10个消费者线程的阻塞调用
 * 
 * 使用wait和notify/notifyAll来实现
 * 
 * 使用Lock和Condition来实现
 * 对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒
 * 
 * @author maple
 */
//同步互斥,等待队列, 基于AQS
package yxxy.c_021;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyContainer2<T> {
    final private LinkedList<T> lists = new LinkedList<>();
    final private int MAX = 10; //最多10个元素
    private int count = 0;
    
    private Lock lock = new ReentrantLock();
    private Condition producer = lock.newCondition();
    private Condition consumer = lock.newCondition();
    
    public void put(T t) {
        try {
            lock.lock();
            while(lists.size() == MAX) { //想想为什么用while而不是用if?
                producer.await();
            }
            
            lists.add(t);
            ++count;
            consumer.signalAll(); //通知消费者线程进行消费
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    
    public T get() {
        T t = null;
        try {
            lock.lock();
            while(lists.size() == 0) {
                consumer.await();
            }
            t = lists.removeFirst();
            count --;
            producer.signalAll(); //通知生产者进行生产
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return t;
    }
    
    public static void main(String[] args) {
        MyContainer2<String> c = new MyContainer2<>();
        //启动消费者线程
        for(int i=0; i<10; i++) {
            new Thread(()->{
                for(int j=0; j<5; j++) System.out.println(c.get());
            }, "c" + i).start();
        }
        
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        //启动生产者线程
        for(int i=0; i<2; i++) {
            new Thread(()->{
                for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
            }, "p" + i).start();
        }
    }
}



转载于:https://www.cnblogs.com/leihuazhe/p/7792239.html

相关文章:

  • Java日志框架-logback的介绍及配置使用方法(纯Java工程)(转)
  • 行外人浅谈“云计算”
  • PE 文件格式 详解 二
  • Linux Mint 教程
  • Jenkins-权限控制
  • 阿里 Linux服务器外网无法连接MySQL解决方法
  • C语言博客作业--嵌套循环
  • java获取当前上一周、上一月、上一年的时间
  • mysql-proxy实现读写分离
  • Linux基本命令—权限管理、文件搜索、帮助、压缩解压、网络通信
  • 中英文金额大写转换器
  • 计算机基础作业
  • 应急响应小总结
  • 课后作业-阅读任务-阅读提问-3
  • HttpClient实现POST参数提交
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • 03Go 类型总结
  • EventListener原理
  • exports和module.exports
  • iOS 颜色设置看我就够了
  • Java,console输出实时的转向GUI textbox
  • Python学习之路16-使用API
  • Sass 快速入门教程
  • Wamp集成环境 添加PHP的新版本
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 构造函数(constructor)与原型链(prototype)关系
  • 前端性能优化--懒加载和预加载
  • 浅谈Golang中select的用法
  • 深度学习在携程攻略社区的应用
  • 使用 QuickBI 搭建酷炫可视化分析
  • 思考 CSS 架构
  • 一份游戏开发学习路线
  • 追踪解析 FutureTask 源码
  • 【干货分享】dos命令大全
  • linux 淘宝开源监控工具tsar
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (cljs/run-at (JSVM. :browser) 搭建刚好可用的开发环境!)
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (MATLAB)第五章-矩阵运算
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (第27天)Oracle 数据泵转换分区表
  • (二)丶RabbitMQ的六大核心
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (十五)devops持续集成开发——jenkins流水线构建策略配置及触发器的使用
  • (四)linux文件内容查看
  • (转)linux下的时间函数使用
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • (轉貼) 2008 Altera 亞洲創新大賽 台灣學生成果傲視全球 [照片花絮] (SOC) (News)
  • ****Linux下Mysql的安装和配置
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET BackgroundWorker
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .net 提取注释生成API文档 帮助文档
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)