--------------------ASP.Net+Android+IOS開發、.Net培訓、期待與您交流! --------------------
1. 生產者和消費者
1. 概述
可以有多個消費者,也可以有多個生產者,他們可以一邊生產一邊消費。
注意:
不管是消費者還是生產者,在生產和消費的前提下,都要判斷一下。要用while()循環判斷,,如果用if()的話,有可能會發生連續生產或者連續消費,這樣就不是一對一了,喚醒的話,就繼續執行下面的語句,不再判斷的原因。
如果用while()進行判斷的話,就可以循環判斷,防止前面的情況發生,但是要用signalAll()或notifyAll(),這樣可以避免死鎖。要是用signal()或notify()的話,會產生死鎖。
2.(Lock)
1.5新特性:
Lock和Condition對象。
Lock替換了synchronized,以前鎖是看不見的,替換成Lock可以看見的。可以使用Lock(接口)子類對象進行管理鎖,lock()方法獲取鎖,unlock()方法釋放鎖。
Condition替換了Object類中的wait(),notify(),notifyAll()方法。
Condition對象通過鎖來獲取,newCondition()方法獲取。
Conditioncondition=lock.newCondition()
condition.await()替換了wait()
condition.signal()替換了notify()
condition.signalAll()替換了notifyAll()
3.示例1
這是使用的是一個鎖,一個Condition對象
importjava.util.concurrent.locks.Condition;
importjava.util.concurrent.locks.Lock;
importjava.util.concurrent.locks.ReentrantLock;
/*資源*/
public class Resource {
private String name;
private int count = 1;
private boolean flag = false;
private Lock lock = new ReentrantLock();//鎖
private Condition condition = lock.newCondition();//獲取Condition對象
/* 生產 */
public void set(String name) throws InterruptedException {
lock.lock();
try {
while (flag)
condition.await();//線程等待
this.name = name + ":" + (count++);
System.out.println(Thread.currentThread().getName() +"生產者生產:"
+ this.name);
this.flag = true;
condition.signalAll();//喚醒線程所有
} finally {
lock.unlock();
}
}
publicvoid show() throws InterruptedException {
lock.lock();
try{
while(!flag)
condition.await();//線程等待
System.out.println(Thread.currentThread().getName()+ "取出第"
+this.name );
this.flag= false;
condition.signalAll();//喚醒所有線程
}finally {
lock.unlock();
}
}
}
/*生產者*/
public class Produce implements Runnable {
private Resource re = null;
public Produce(Resource re) {
this.re = re;
}
public void run() {
while (true) {
try {
re.set("商品");
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/*消費者*/
public class Customer implements Runnable {
private Resource re = null;
public Customer(Resource re) {
this.re = re;
}
public void run() {
while (true) {
try {
re.show();
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/*測試類*/
public class Text {
public static void main(String[] agrs) {
Resource r = new Resource();
new Thread(new Produce(r), "---生產者A----").start();
new Thread(new Produce(r), "---生產者B----").start();
new Thread(new Customer(r), "++消費者1++").start();
new Thread(new Customer(r), "++消費者2++").start();
new Thread(new Customer(r), "++消費者3++").start();
}
}
結果:
---生產者A----生產者生產:商品:1
++消費者1++取出第商品:1
---生產者B----生產者生產:商品:2
++消費者3++取出第商品:2
---生產者B----生產者生產:商品:3
++消費者1++取出第商品:3
---生產者A----生產者生產:商品:4
++消費者2++取出第商品:4
---生產者A----生產者生產:商品:5
++消費者3++取出第商品:5
---生產者B----生產者生產:商品:6
++消費者2++取出第商品:6
---生產者A----生產者生產:商品:7
++消費者1++取出第商品:7
---生產者B----生產者生產:商品:8
++消費者2++取出第商品:8
---生產者A----生產者生產:商品:9
++消費者3++取出第商品:9
---生產者B----生產者生產:商品:10
++消費者2++取出第商品:10
---生產者A----生產者生產:商品:11
++消費者3++取出第商品:11
4.示例2
使用的是一個鎖,多個Condition對象,不同的Condition對象喚醒的另一個Condition對象,這樣就可以不使用的signalAll()方法,
思路:參生產者升生產出商品後,通知消費着(喚醒消費者),消費者消費商品後,通知生產者(喚醒生產者)
只更改資源類就可以,其他的類不用更改。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/*資源*/
public class Resource {
privateString name;
privateint count = 1;
privateboolean flag = false;
privateLock lock = new ReentrantLock();//鎖
privateCondition condition_pro = lock.newCondition();//獲取生產者的Condition對象
privateCondition condition_cus = lock.newCondition();//獲取消費者Condition對象
/* 生產 */
publicvoid set(String name) throws InterruptedException {
lock.lock();
try{
while(flag)
condition_pro.await();//線程等待(生產者不符合條件)
this.name = name + ":" +(count++);
System.out.println(Thread.currentThread().getName()+ "生產者生產:"
+ this.name);
this.flag= true;
condition_cus.signal();//喚醒消費者
}finally {
lock.unlock();
}
}
public voidshow() throws InterruptedException {
lock.lock();
try {
while(!flag)
condition_cus.await();//線程等待 消費者,不符合條件
System.out.println(Thread.currentThread().getName()+ "取出第"
+this.name );
this.flag= false;
condition_pro.signalAll();//喚醒生產者
}finally {
lock.unlock();
}
}
}
結果:
---生產者A----生產者生產:商品:1
++消費者1++取出第商品:1
---生產者B----生產者生產:商品:2
++消費者2++取出第商品:2
---生產者A----生產者生產:商品:3
++消費者3++取出第商品:3
---生產者B----生產者生產:商品:4
++消費者2++取出第商品:4
---生產者A----生產者生產:商品:5
++消費者1++取出第商品:5
---生產者B----生產者生產:商品:6
++消費者3++取出第商品:6
---生產者A----生產者生產:商品:7
++消費者1++取出第商品:7
---生產者B----生產者生產:商品:8
++消費者2++取出第商品:8
---生產者A----生產者生產:商品:9
++消費者1++取出第商品:9
---生產者B----生產者生產:商品:10
++消費者3++取出第商品:10
---生產者A----生產者生產:商品:11
++消費者2++取出第商品:11
---生產者B----生產者生產:商品:12
++消費者3++取出第商品:12
---生產者A----生產者生產:商品:13
++消費者3++取出第商品:13
---生產者B----生產者生產:商品:14
++消費者1++取出第商品:14
---生產者B----生產者生產:商品:15
++消費者3++取出第商品:15
---生產者A----生產者生產:商品:16
++消費者2++取出第商品:16
--------------------ASP.Net+Android+IOS開發、.Net培訓、期待與您交流!
--------------------