能够运行的代码,简单的生产者和消费者代码
备注:我自己写的时候,总是把在不同的对象上面调用,所以导致一直报错,下面会有报错代码
1)通过synchronized获取对象的锁,一定要有synchronized同步中wait和notify
2)如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。
3)条件满足则执行对应的逻辑。
while(true) synchronized (对象){ //如果仓库满了,就让他等待消费 while(条件不满足){ 对象.wait(); } //处理自己的逻辑 DoSomeThing(); //唤醒在对象上等待的其他线程 对象.notifyAll(); } }
package cn.enjoyedu.ch1.wn;
/**
* @author: honry.guan
* @create: 2020-06-09 23:06
**/
public class TestBroad {
private Integer sum;
public TestBroad(Integer sum) {
this.sum = sum;
System.out.println("初始面包:"+sum);
}
static class Product extends Thread{
private TestBroad testBroad;
public Product(TestBroad testBroad,String name) {
super(name);
this.testBroad = testBroad;
}
@Override
public void run() {
try {
while(true){
synchronized (testBroad){
//如果仓库满了,就让他等待消费
while(testBroad.sum >= 20){
System.out.println("当前库存满了,等待消费:"+testBroad.sum);
testBroad.wait();
}
//库存还没有满,新增库存,并且唤醒所有的消费者和生产者
testBroad.sum = testBroad.sum +1;
System.out.println("生产者生产了一个面包:"+testBroad.sum);
testBroad.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Customer extends Thread{
private TestBroad testBroad;
public Customer(TestBroad testBroad,String name) {
super(name);
this.testBroad = testBroad;
}
@Override
public void run() {
try {
while(true){
synchronized (testBroad) {
System.out.println(Thread.currentThread().getName());
while (testBroad.sum <= 0) {
System.out.println("当前库存不足,等待生产:" + testBroad.sum);
testBroad.wait();
}
//当有足够的库存的时候,唤醒所有生产者和消费者
testBroad.sum = testBroad.sum - 1;
System.out.println("消费者吃了一个面包:" + testBroad.sum);
testBroad.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestBroad testBroad = new TestBroad(10);
Integer sum = 10;
for (int i = 0; i < 3; i++) {
new Product(testBroad,"生产者-"+i).start();
new Customer(testBroad,"消费者-"+i).start();
}
}
}
运行结果
初始面包:10
生产者生产了一个面包:11
生产者生产了一个面包:12
生产者生产了一个面包:13
生产者生产了一个面包:14
生产者生产了一个面包:15
生产者生产了一个面包:16
生产者生产了一个面包:17
生产者生产了一个面包:18
生产者生产了一个面包:19
生产者生产了一个面包:20
当前库存满了,等待消费:20
消费者吃了一个面包:19
生产者生产了一个面包:20
错误的加锁导致的报错
对integer加锁导致错误,在执行sum = sum - 1;,sum对象已经发生了改变,不再是原来的对象了,所以会报错
package cn.enjoyedu.ch1.wn;
/**
* @author: honry.guan
* @create: 2020-06-09 23:06
**/
public class TestBroad2 {
private Integer sum;
public TestBroad2(Integer sum) {
this.sum = sum;
System.out.println("初始面包:"+sum);
}
static class Product extends Thread{
private Integer sum;
public Product(Integer sum,String name) {
super(name);
this.sum = sum;
}
@Override
public void run() {
try {
while(true){
synchronized (sum){
System.out.println("------"+Thread.currentThread().getName()+"===="+sum.hashCode());
System.out.println(sum.hashCode());
//如果仓库满了,就让他等待消费
while(sum >= 20){
System.out.println("当前库存满了,等待消费:"+sum);
sum.wait();
}
//库存还没有满,新增库存,并且唤醒所有的消费者和生产者
sum = sum +1;
System.out.println("生产者生产了一个面包:"+sum);
sum.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Customer extends Thread{
private Integer sum;
public Customer(Integer sum,String name) {
super(name);
this.sum = sum;
}
@Override
public void run() {
try {
while(true){
synchronized (sum) {
System.out.println("------"+Thread.currentThread().getName()+"===="+sum.hashCode());
while (sum <= 0) {
System.out.println("当前库存不足,等待生产:" + sum);
sum.wait();
}
//当有足够的库存的时候,唤醒所有生产者和消费者
sum = sum - 1;
System.out.println("消费者吃了一个面包:" + sum);
sum.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
TestBroad2 testBroad = new TestBroad2(10);
Integer sum = 10;
for (int i = 0; i < 3; i++) {
new Product(sum,"生产者-"+i).start();
new Customer(sum,"消费者-"+i).start();
}
}
}
报错:解决方法就是用第一个demo,把integer对象包装起来
初始面包:10
------生产者-0====10
10
生产者生产了一个面包:11
Exception in thread "生产者-0" ------消费者-0====10
消费者吃了一个面包:9
java.lang.IllegalMonitorStateException
------生产者-1====10
at java.lang.Object.notifyAll(Native Method)
at cn.enjoyedu.ch1.wn.TestBroad2$Product.run(TestBroad2.java:38)
Exception in thread "消费者-0" 10
生产者生产了一个面包:11
java.lang.IllegalMonitorStateException