摘要:寄語天眼之父南仁東,心無旁騖,為崇山峻嶺間的中國天眼燃盡生命,看似一口大鍋,天眼是世界上最大最靈敏的單口徑射電望遠鏡,可以接受百億光年外的電磁信號。南仁東總工程師執著追求科學夢想的精神,將激勵一代又一代科技工作者繼續奮斗,勇攀世界科技高峰。
歡迎進入JAVA基礎課程
博客地址:https://segmentfault.com/a/11...
本系列文章將主要針對JAVA一些基礎知識點進行講解,為平時歸納所總結,不管是剛接觸JAVA開發菜鳥還是業界資深人士,都希望對廣大同行帶來一些幫助。若有問題請及時留言或加QQ:243042162。
寄語:生產者消費者問題
“天眼”之父南仁東,心無旁騖,為崇山峻嶺間的中國“天眼”燃盡生命,看似一口“大鍋”,天眼是世界上最大、最靈敏的單口徑射電望遠鏡,可以接受百億光年外的電磁信號。南仁東總工程師執著追求科學夢想的精神,將激勵一代又一代科技工作者繼續奮斗,勇攀世界科技高峰。作為IT界的從業者,我們需要緊跟時代的步伐,踏過平庸,一生為科技筑夢。
1. 背景
生產者消費者問題(Producer-consumer problem),也稱有限緩沖問題(Bounded-buffer problem),是一個多線程同步問題的經典案例。生產者生成一定量的數據放到緩沖區中,然后重復此過程;與此同時,消費者也在緩沖區消耗這些數據。生產者和消費者之間必須保持同步,要保證生產者不會在緩沖區滿時放入數據,消費者也不會在緩沖區空時消耗數據。不夠完善的解決方法容易出現死鎖的情況,此時進程都在等待喚醒。
2. 條件
生產者僅僅在倉儲未滿時候生產, 倉滿則停止生產.
生產者在生產出可消費產品時候, 應該通知等待的消費者去消費.
消費者僅僅在倉儲有產品時候才能消費, 倉空則等待.
消費者發現倉儲沒產品可消費時候會通知生產者生產.
3.實現方式
wait() / notify()方法
await() / signal()方法
BlockingQueue阻塞隊列方法
Semaphore方法
PipedInputStream / PipedOutputStream
下面主要針對前面三種方式做代碼實現
(1) wait() / notify()方法
public class ProducerMain {
private static Integer count=0;
private final Integer full=10;
private static String LOCK="LOCK";
class Producer implements Runnable{
@Override
public void run() {
// for(int i=0;i<10;i++){
// try {
// Thread.sleep(3000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
synchronized (LOCK){
while(count==full){
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName()+"生產者生產,目前共生產了:"+count);
LOCK.notifyAll();
}
}
}
class Consumer implements Runnable{
@Override
public void run() {
synchronized (LOCK){
while (count==0){
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName()+"生產者消費,目前共剩余:"+count);
LOCK.notifyAll();
}
}
}
public static void main(String[] args) {
ProducerMain producer = new ProducerMain();
new Thread(producer.new Producer()).start();
new Thread(producer.new Consumer()).start();
new Thread(producer.new Producer()).start();
new Thread(producer.new Consumer()).start();
new Thread(producer.new Producer()).start();
new Thread(producer.new Consumer()).start();
new Thread(producer.new Producer()).start();
new Thread(producer.new Consumer()).start();
}
}
輸出結果
Thread-0生產者生產,目前共生產了:1 Thread-5生產者消費,目前共剩余:0 Thread-2生產者生產,目前共生產了:1 Thread-7生產者消費,目前共剩余:0 Thread-6生產者生產,目前共生產了:1 Thread-1生產者消費,目前共剩余:0 Thread-4生產者生產,目前共生產了:1 Thread-3生產者消費,目前共剩余:0
(2)await() / signal()方法
public class ReentrantLockDemo {
private static Integer count = 0;
private final Integer FULL = 10;
final Lock lock = new ReentrantLock();
final Condition NotFull = lock.newCondition();
final Condition NotEmpty = lock.newCondition();
class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
lock.lock();
try {
while (count == FULL) {
try {
NotFull.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName()
+ "生產者生產,目前總共有" + count);
NotEmpty.signal();
} finally {
lock.unlock();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
lock.lock();
try {
while (count == 0) {
try {
NotEmpty.await();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName()
+ "消費者消費,目前總共有" + count);
NotFull.signal();
} finally {
lock.unlock();
}
}
}
}
public static void main(String[] args) throws Exception {
ReentrantLockDemo hosee = new ReentrantLockDemo();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
}
}
輸出結果
Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-0生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-0生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-0生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-0生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-4生產者生產,目前總共有2 Thread-5消費者消費,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-2生產者生產,目前總共有2 Thread-1消費者消費,目前總共有1 Thread-6生產者生產,目前總共有2 Thread-7消費者消費,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0
(3)BlockingQueue阻塞隊列方法
public class BlockingQueueMain {
private static Integer count = 0;
final BlockingQueue bq = new ArrayBlockingQueue(10);
class Producer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
try {
bq.put(1);
count++;
System.out.println(Thread.currentThread().getName()
+ "生產者生產,目前總共有" + count);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Consumer implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
try {
bq.take();
count--;
System.out.println(Thread.currentThread().getName()
+ "消費者消費,目前總共有" + count);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws Exception {
BlockingQueueMain hosee = new BlockingQueueMain();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
new Thread(hosee.new Producer()).start();
new Thread(hosee.new Consumer()).start();
}
}
輸出結果
Thread-1消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-0生產者生產,目前總共有0 Thread-5消費者消費,目前總共有0 Thread-3消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-6生產者生產,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-1消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-6生產者生產,目前總共有0 Thread-7消費者消費,目前總共有0 Thread-4生產者生產,目前總共有0 Thread-1消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-4生產者生產,目前總共有1 Thread-1消費者消費,目前總共有0 Thread-0生產者生產,目前總共有1 Thread-5消費者消費,目前總共有0 Thread-2生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-7消費者消費,目前總共有0 Thread-4生產者生產,目前總共有2 Thread-0生產者生產,目前總共有1 Thread-1消費者消費,目前總共有0 Thread-5消費者消費,目前總共有1 Thread-2生產者生產,目前總共有1 Thread-3消費者消費,目前總共有0 Thread-6生產者生產,目前總共有1 Thread-7消費者消費,目前總共有0
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/104683.html
摘要:寄語天眼之父南仁東,心無旁騖,為崇山峻嶺間的中國天眼燃盡生命,看似一口大鍋,天眼是世界上最大最靈敏的單口徑射電望遠鏡,可以接受百億光年外的電磁信號。南仁東總工程師執著追求科學夢想的精神,將激勵一代又一代科技工作者繼續奮斗,勇攀世界科技高峰。 歡迎進入JAVA基礎課程 博客地址:https://segmentfault.com/a/11...本系列文章將主要針對JAVA一些基礎知識點進行...
摘要:歡迎進入基礎課程博客地址本系列文章將主要針對一些基礎知識點進行講解,為平時歸納所總結,不管是剛接觸開發菜鳥還是業界資深人士,都希望對廣大同行帶來一些幫助。若有問題請及時留言或加。 歡迎進入JAVA基礎課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對JAVA一些基礎知識點進行講解,為平時歸納所總結,不管是剛接觸JAVA開發菜鳥還是業界...
摘要:歡迎進入基礎課程博客地址本系列文章將主要針對一些基礎知識點進行講解,為平時歸納所總結,不管是剛接觸開發菜鳥還是業界資深人士,都希望對廣大同行帶來一些幫助。若有問題請及時留言或加。 歡迎進入JAVA基礎課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對JAVA一些基礎知識點進行講解,為平時歸納所總結,不管是剛接觸JAVA開發菜鳥還是業界...
摘要:一個進程可以有多個線程。線程又叫做輕量級進程。這樣兩個進程相互無休止地等待下去,均無法繼續執行,此時兩個進程陷入死鎖狀態。不剝奪條件進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能由獲得該資源的進程自己來釋放只能是主動釋放。 歡迎進入JAVA基礎課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對JAVA一些基礎知識點進...
摘要:一個進程可以有多個線程。線程又叫做輕量級進程。這樣兩個進程相互無休止地等待下去,均無法繼續執行,此時兩個進程陷入死鎖狀態。不剝奪條件進程所獲得的資源在未使用完畢之前,不能被其他進程強行奪走,即只能由獲得該資源的進程自己來釋放只能是主動釋放。 歡迎進入JAVA基礎課程 博客地址:https://blog.csdn.net/houjiyu...本系列文章將主要針對JAVA一些基礎知識點進...
閱讀 998·2021-09-07 09:58
閱讀 2964·2021-08-31 09:42
閱讀 2988·2019-08-30 14:18
閱讀 3218·2019-08-30 14:08
閱讀 2007·2019-08-30 12:57
閱讀 2909·2019-08-26 13:31
閱讀 1468·2019-08-26 11:58
閱讀 1191·2019-08-23 18:06