能夠運行的代碼,簡單的生產者和消費者代碼
備註:我自己寫的時候,總是把在不同的對象上面調用,所以導致一直報錯,下面會有報錯代碼
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