1.普通的生产消费者例子
synchronized JVM提供的多线程同步,在少量线程下,足够用来
this.wait() 线程等待
notify(), JVM去随机唤醒一个线程,然后拿到锁 【不用竞争】
notifyall() JVM去唤醒所有线程,然后竞争拿到锁【需要竞争】
多线程,小心死锁和没同步住数据
package com.test.thread.producerconsumer;
/**
* 资源类
* @author 汪兴安
*
*
* bug 1.synchronized 方法中if this.wait();需要改成while this.wait(); 导致现象:多生产或多消费
* 2.notify(); 必须换成成notifyAll() ,不然会死锁 导致现象:程序无限等待下去
*
*/
public class Resource {
// 商品名称
private String name;
private String names;
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
// 商品ID
private int id = 1;
// 是否有商品
private boolean hasGoods = false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 生产方法
public synchronized void set(String name) {
// 有商品
while (hasGoods) { //if 多线程用if,判断是作死
try {
//等等,已经有商品了,当然可以休息下
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setName(name + "_" + id);
id++;
System.out.println("生产名称:" + Thread.currentThread().getName()
+ "以生产商品为:" + this.name);
// 有商品
hasGoods = true;
// 想通知消费线程来消费
notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
}
// 消费方法
public synchronized void out() {
// 没商品
while (!hasGoods) {//if 多线程用if,判断是作死 应该放在while里面,因为如果是if的话,当被唤醒了,直接在if里面,往下执行了
try {
// 等等
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消费名称:" + Thread.currentThread().getName()
+ "以消费商品为:" + this.name);
// 无商品
hasGoods = false;
// 想通知生产线程来消费
notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
}
}
package com.test.thread.producerconsumer;
/**
* 生产者 线程
* @author 汪兴安
*
*/
public class Producter implements Runnable {
//持有对方的引用
private Resource resource;
public Producter(Resource resource)
{
this.resource=resource;
}
public void run()
{
//不断生产
while(true)
{
resource.set(resource.getNames());
}
}
}
package com.test.thread.producerconsumer;
/**
* 不断去消费 线程
* @author 汪兴安
*
*/
public class Customer implements Runnable {
//持有对方的引用
private Resource resource;
public Customer(Resource resource)
{
this.resource=resource;
}
public void run()
{
//不断消费
while(true)
{
resource.out();
}
}
}
package com.test.thread.producerconsumer;
/**
* 多线程,就是要模拟多个请求才行
* @author 汪兴安
*
*/
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Resource resource=new Resource();
resource.setNames("iphone");
Producter p=new Producter(resource);
Customer c=new Customer(resource);
new Thread(p).start();//一个工厂 生产
new Thread(c).start(); //一群消费者
new Thread(c).start();
new Thread(c).start();
new Thread(c).start();
new Thread(c).start();
new Thread(c).start();
}
}
===================================华丽的分开了==============================================================================
其他类不变,就Resource变了,注释非常多,自己体会去吧
package com.test.thread.producerconsumer.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
/**
* 资源类
*
* @author 汪兴安
*
* Lock 优点:1.显示化,结构灵活,控制细粒度高,可以更高效
*
*
*
* synchronized的wait,nofity,notify是一套的,但Lock与condition可以组合多个,类似2分法,效率大大的提高
*
* bug 1.synchronized 方法中if this.wait();需要改成while this.wait();
* 导致现象:多生产或多消费 2.notify(); 必须换成成notifyAll() ,不然会死锁 导致现象:程序无限等待下去
*
*/
public class Resource {
// 商品名称
private String name;
private String names;
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
// 商品ID
private int id = 1;
// 是否有商品
private boolean hasGoods = false;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 显示的拿到锁对象
private Lock lock = new ReentrantLock();
// 获取锁的监控器对象-----更好隔离,拆分更细 与锁lock组合使用
private Condition condition = lock.newCondition();
// 获取锁的监控器对象-----更好隔离,拆分更细 与锁lock组合使用
private Condition conditionOut = lock.newCondition();
// 生产方法
public void set(String name) {
lock.lock();// 获取锁
try {
// 有商品
while (hasGoods) { // if 多线程用if,判断是作死
try {
// 等等,已经有商品了,当然可以休息下
// this.wait();
condition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
this.setName(name + "_" + id);
id++;
System.out.println("生产名称:" + Thread.currentThread().getName()
+ "以生产商品为:" + this.name);
// 有商品
hasGoods = true;
// 想通知消费线程来消费
// notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
conditionOut.signalAll();
} finally {
lock.unlock();
}
}
// 消费方法
public void out() {
lock.lock();// 获取锁
try {
// 没商品
while (!hasGoods) {// if 多线程用if,判断是作死
// 应该放在while里面,因为如果是if的话,当被唤醒了,直接在if里面,往下执行了
try {
// 等等
// this.wait();
conditionOut.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消费名称:" + Thread.currentThread().getName()
+ "以消费商品为:" + this.name);
// 无商品
hasGoods = false;
// 想通知生产线程来消费
// notifyAll();// 2.notify(); 必须换成成notifyAll() ,不然会死锁
condition.signalAll();
} finally {
lock.unlock();
}
}
}