学习和理解JAVA线程同步--生产者与消费者例子
来源:互联网 发布:淘宝店铺怎么暂停营业 编辑:程序博客网 时间:2024/05/16 05:22
JAVA线程同步通常需要使用sychronized对临界资源进行加锁,所谓的临界资源就是指这些线程共同使用的资源。
sychronized通常是放在方法名前,这是表示这个方法是同步的,实际上是对this加锁。
或者放在一个对象前,对某个共同使用的对象加锁。
生产者和消费者的例子是非常经典的,这里需要定义一个池子,用于往里放入产品。定义生产者不断生产产品,当池子不满的情况下可以继续放,满了则等待。
消费者一直从池子取,池子空则等待。
我们使用实现runnable来实现生产者和消费者。
写一个同步栈作为池子,对push和pop方法进行同步。
代码如下:
class SycnStack{private Integer index=0;private char[] data;public SycnStack(int num){data = new char[num];}public void push(char c){synchronized (this) {//对index加锁为何不行???必须thiswhile(index==data.length-1) {System.out.println("池子已经满,不能放入了!"+Thread.currentThread().toString());try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notify();//获取锁data[index]=c;System.out.println("放入"+c+" "+Thread.currentThread().toString());index++;}}public Character pop(){synchronized (this) {while(index==0){System.out.println("池子已经空了,取不了了!"+Thread.currentThread().toString());try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.notify();index--;char c = data[index];System.out.println("取出"+c+" "+Thread.currentThread().toString());return c;}}
然后写生产者和消费者,其run方法就是不断的生产产品放入池子或取出产品:
class Producer implements Runnable{private SycnStack stack;public Producer(SycnStack stack){this.stack = stack;}@Overridepublic void run() {int i=10;while(i-->0){stack.push( (char)(26*Math.random()+'A'));Thread.yield();}}}class Consumer implements Runnable{private SycnStack stack;public Consumer(SycnStack stack){this.stack = stack;}@Overridepublic void run() {int i=10;while(i-->0){stack.pop();Thread.yield();}}}main方法如下,创建一个栈用于放产品,然后创建生产者和消费者都用这个产品栈,并启动:
public class ProductorConsumer {public static void main(String[] args){SycnStack s = new SycnStack(5);new Thread(new Producer(s)).start();new Thread(new Consumer(s)).start();}}结果如下:
放入G Thread[Thread-0,5,main]放入L Thread[Thread-0,5,main]放入D Thread[Thread-0,5,main]放入K Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出K Thread[Thread-1,5,main]放入P Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出P Thread[Thread-1,5,main]放入E Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出E Thread[Thread-1,5,main]放入M Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出M Thread[Thread-1,5,main]放入P Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出P Thread[Thread-1,5,main]放入Q Thread[Thread-0,5,main]池子已经满,不能放入了!Thread[Thread-0,5,main]取出Q Thread[Thread-1,5,main]放入L Thread[Thread-0,5,main]取出L Thread[Thread-1,5,main]取出D Thread[Thread-1,5,main]取出L Thread[Thread-1,5,main]取出G Thread[Thread-1,5,main]
再看同步栈的代码第十行,是对this加锁,指的就是对当前这个栈加锁。
之前我测试使用对index加锁,发现是会报错的,我想可能是因为临界资源不仅是index,还有data,如果只对index加锁,当一个线程在用栈的时候,另一个线程仍然能够使用这个栈,就会造成index的混乱之后就报错了。
如果谁有更详细的解释也可以告诉我。
- 学习和理解JAVA线程同步--生产者与消费者例子
- 学习和理解JAVA线程同步--生产者与消费者例子
- JAVA线程同步生产者/消费者简单例子
- 线程同步 生产者消费者小例子
- 线程同步生产者和消费者c和java不同实现
- Java经典线程同步问题------生产者与消费者
- Java经典线程同步问题------生产者与消费者
- java模拟生产者与消费者问题(线程同步)
- java实现线程同步一个生产者和一个消费者
- JAVA线程同步——消费者和生产者模式
- Java线程安全总结(包含生产者和消费者例子)
- java实现的生产者和消费者问题-涉及线程同步与通信
- java线程 生产者与消费者
- java线程 生产者与消费者
- 线程同步学习笔记(生产者消费者)
- 同步线程--生产者与消费者模式
- 消费者与生产者线程同步程序
- 线程同步(消费者与生产者)
- 系统设计黄金法则:简单之美
- Handler的多线程处理
- 设计模式原则(1)单一职责原则
- 如何设计数据库
- 将服务器的网页报表保存到excel文件
- 学习和理解JAVA线程同步--生产者与消费者例子
- JSP_SERVLET(一)
- xml-可扩展标记语言
- Linux开机自动运行脚本程序
- js删除array
- 各种总线match匹配函数
- sudo apt-get install E: 软件包 * 还没有可供安装的候选者 --解决方法
- JSP_SERVLET(二)
- myeclipse中jsp/html页面自动提示的设置