java多线程解决同步问题的几种方式、原理和代码
来源:互联网 发布:海信网络机顶盒ip903h 编辑:程序博客网 时间:2024/05/18 01:01
在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。管道方法不建议使用,阻塞队列方法在问题4已有描述,现只提供前两种实现方法。
- wait()/notify()方法
- await()/signal()方法
- BlockingQueue阻塞队列方法
- PipedInputStream/PipedOutputStream
阻塞队列的一个简单实现:
public class BlockingQueue { private List queue = new LinkedList(); private int limit = 10; public BlockingQueue(int limit){ this.limit = limit; } public synchronized void enqueue(Object item)throws InterruptedException { while(this.queue.size() == this.limit) { wait(); } if(this.queue.size() == 0) { notifyAll(); } this.queue.add(item); } public synchronized Object dequeue() throws InterruptedException{ while(this.queue.size() == 0){ wait(); } if(this.queue.size() == this.limit){ notifyAll(); } return this.queue.remove(0); }}
在enqueue和dequeue方法内部,只有队列的大小等于上限(limit)或者下限(0)时,才调用notifyAll方法。如果队列的大小既不等于上限,也不等于下限,任何线程调用enqueue或者dequeue方法时,都不会阻塞,都能够正常的往队列中添加或者移除元素。- wait()/notify()方法
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。
生产者类:
public class Producer extends Thread { // 每次生产的产品数量 private int num; // 所在放置的仓库 private Storage storage; // 构造函数,设置仓库 public Producer(Storage storage) { this.storage = storage; } // 线程run函数 public void run() { produce(num); } // 调用仓库Storage的生产函数 public void produce(int num) { storage.produce(num); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; }}
消费者类:
public class Consumer extends Thread { // 每次消费的产品数量 private int num; // 所在放置的仓库 private Storage storage; // 构造函数,设置仓库 public Consumer(Storage storage) { this.storage = storage; } // 线程run函数 public void run() { consume(num); } // 调用仓库Storage的生产函数 public void consume(int num) { storage.consume(num); } // get/set方法 public int getNum() { return num; } public void setNum(int num) { this.num = num; } public Storage getStorage() { return storage; } public void setStorage(Storage storage) { this.storage = storage; }}
仓库类:(wait()/notify()方法)
public class Storage { // 仓库最大存储量 private final int MAX_SIZE = 100; // 仓库存储的载体 private LinkedList<Object> list = new LinkedList<Object>(); // 生产num个产品 public void produce(int num) { // 同步代码段 synchronized (list) { // 如果仓库剩余容量不足 while (list.size() + num > MAX_SIZE) {//相当于缓冲区满,生产者则等待 System.out.print("【要生产的产品数量】:" + num); System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!"); try { list.wait();// 由于条件不满足,生产阻塞 } catch (InterruptedException e) { e.printStackTrace(); } } // 生产条件满足情况下,生产num个产品 for (int i = 1; i <= num; ++i) { list.add(new Object()); } System.out.print("【已经生产产品数】:" + num); System.out.println(" 【现仓储量为】:" + list.size()); list.notifyAll(); } } // 消费num个产品 public void consume(int num) { // 同步代码段 synchronized (list) { // 如果仓库存储量不足 while (list.size() < num) {//相当于缓冲区空,消费者则等待 System.out.print("【要消费的产品数量】:" + num); System.out.println(" 【库存量】:" + list.size() + " 暂时不能执行生产任务!"); try { // 由于条件不满足,消费阻塞 list.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 消费条件满足情况下,消费num个产品 for (int i = 1; i <= num; ++i) { list.remove(); } System.out.print("【已经消费产品数】:" + num); System.out.println(" 【现仓储)量为】:" + list.size()); list.notifyAll(); } } // get/set方法 public LinkedList<Object> getList() { return list; } public void setList(LinkedList<Object> list) { this.list = list; } public int getMAX_SIZE() { return MAX_SIZE; }}
0 0
- java多线程解决同步问题的几种方式、原理和代码
- Java多线程同步的几种方式
- Java多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Pthread多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- Linux多线程同步的几种方式
- 多线程的几种同步方式
- 多线程几种同步方式
- 多线程_同步代码块的方式解决线程安全问题
- 知识管理,浏览器收藏夹,经常访问的网站
- linux网络通信并发程序设计(一)
- UNIX网络编程——概述
- JS笔记3-笔记整理自智能社JS教程
- 管道,匿名管道及其命名管道的解析
- java多线程解决同步问题的几种方式、原理和代码
- OpenGl的glMatrixMode函数理解
- libev 学习笔记之timer实现原理
- C语言中的static函数
- 安卓学习之—自定义Dialog
- 杂乱总结
- 【SDOI2011】染色
- 1012. The Best Rank (25)
- session序列化异常、session的销毁方式