1. 程式人生 > >由生產者/消費者問題看JAVA多執行緒

由生產者/消費者問題看JAVA多執行緒

生產者消費者問題是研究多執行緒程式時繞不開的問題,它的描述是有一塊生產者和消費者共享的有界緩衝區,生產者往緩衝區放入產品,消費者從緩衝區取走產品,這個過程可以無休止的執行,不能因緩衝區滿生產者放不進產品而終止,也不能因緩衝區空消費者無產品可取而終止。 解決生產者消費者問題的方法有兩種,一種是採用某種機制保持生產者和消費者之間的同步,一種是在生產者和消費者之間建立一個管道。前一種有較高的效率並且可控制性較好,比較常用,後一種由於管道緩衝區不易控制及被傳輸資料物件不易封裝等原因,比較少用。 同步問題的核心在於,CPU是按時間片輪詢的方式執行程式,我們無法知道某一個執行緒是否被執行、是否被搶佔、是否結束等,因此生產者完全可能當緩衝區已滿的時候還在放入產品,消費者也完全可能當緩衝區為空時還在取出產品。 現在同步問題的解決方法一般是採用訊號或者加鎖機制,即生產者執行緒當緩衝區已滿時放棄自己的執行權, 進入等待狀態,並通知消費者執行緒執行。消費者執行緒當緩衝區已空時放棄自己的執行權,進入等待狀態,並通知生產者執行緒執行。這樣一來就保持了執行緒的同步,並 避免了執行緒間互相等待而進入死鎖狀態。        JAVA語言提供了獨立於平臺的執行緒機制,保持了”write once, run anywhere”的特色。同時也提供了對同步機制的良好支援。 在JAVA中,一共有四種方法支援同步,其中三個是同步方法,一個是管道方法。 1.方法wait()/notify() 2.方法await()/signal() 3.阻塞佇列方法BlockingQueue 4.管道方法PipedInputStream/PipedOutputStream 下面我們看各個方法的實現: 1.方法wait()/notify() wait()和notify()是根類Object的兩個方法,也就意味著所有的JAVA類都會具有這個兩個方法,為什麼會被這樣設計呢?我們可以認為所有的物件預設都具有一個鎖,雖然我們看不到,也沒有辦法直接操作,但它是存在的。 wait()方法表示:當緩衝區已滿或空時,生產者或消費者執行緒停止自己的執行,放棄鎖,使自己處於等待狀態,讓另一個執行緒開始執行; notify()方法表示:當生產者或消費者對緩衝區放入或取出一個產品時,向另一個執行緒發出可執行通知,同時放棄鎖,使自己處於等待狀態。 下面是一個例子程式碼:
import java.util.LinkedList;

publicclass Sycn1{
    
private LinkedList<Object> myList =new LinkedList<Object>();
    
privateint MAX =10;
    
    
public Sycn1(){
    }

    
    
publicvoid start(){
            
new Producer().start();
            
new Consumer().start();
    }

    
    
publicstatic
void main(String[] args) throws Exception{
        Sycn1 s1 
=new Sycn1();
        s1.start();
    }

    
    
class Producer extends Thread{        
        
publicvoid run(){
            
while(true){
                
synchronized(myList){
                    
try{
                        
while(myList.size() 
== MAX){
                            System.out.println(
"warning: it's full!");
                            myList.wait();
                        }

                        Object o 
=new Object();
                        
if(myList.add(o)){
                            System.out.println(
"Producer: "+ o);
                            myList.notify();
                        }

                    }
catch(InterruptedException ie){
                        System.out.println(
"producer is interrupted!");
                    }

                }

            }

        }

    }

    
    
class Consumer extends Thread{
        
publicvoid run(){
            
while(true){
                
synchronized(myList){
                    
try{
                        
while(myList.size() ==0){
                            System.out.println(
"warning: it's empty!");
                            myList.wait();
                        }

                        Object o 
= myList.removeLast();
                        System.out.println(
"Consumer: "+ o);
                        myList.notify();
                    }
catch(InterruptedException ie){
                        System.out.println(
"consumer is interrupted!");
                    }

                }

            }

        }

    }

    
}
2.方法await()/signal() 在JDK5.0以後,JAVA提供了新的更加健壯的執行緒處理機制,包括 了同步、鎖定、執行緒池等等,它們可以實現更小粒度上的控制。await()和signal()就是其中用來做同步的兩種方法,它們的功能基本上和 wait()/notify()相同,完全可以取代它們,但是它們和新引入的鎖定機制Lock直接掛鉤,具有更大的靈活性。 下面是一個例子程式碼: import java.util.LinkedList;

import java.util.concurrent.locks.*;

publicclass Sycn2{
    
private LinkedList<Object> myList =new LinkedList<Object>();
    
privateint MAX =10;
    
privatefinal Lock lock =new ReentrantLock();
    
privatefinal Condition full = lock.newCondition();
    
privatefinal Condition empty = lock.newCondition();
    
    
public Sycn2(){
    }

    
    
publicvoid start(){
            
new Producer().start();
            
new Consumer().start();
    }

    
    
publicstaticvoid main(String[] args) throws Exception{
        Sycn2 s2 
=new Sycn2();
        s2.start();
    }

    
    
class Producer extends Thread{        
        
publicvoid run(){
            
while(true){
                lock.lock();
                
try{
                    
while(myList.size() == MAX){
                        System.out.println(
"warning: it's full!");
                        full.await();
                    }

                    Object o 
=new Object();
                    
if(myList.add(o)){
                        System.out.println(
"Producer: "+ o);
                        empty.signal();
                    }

                }
catch(InterruptedException ie){
                    System.out.println(
"producer is interrupted!");

相關推薦

生產者/消費者問題JAVA執行

生產者消費者問題是研究多執行緒程式時繞不開的問題,它的描述是有一塊生產者和消費者共享的有界緩衝區,生產者往緩衝區放入產品,消費者從緩衝區取走產品,這個過程可以無休止的執行,不能因緩衝區滿生產者放不進產品而終止,也不能因緩衝區空消費者無產品可取而終止。 解決生產者消費者問題的

從ConcurrentHashMap的演進Java執行核心技術

執行緒不安全的HashMap 眾所周知,HashMap是非執行緒安全的。而HashMap的執行緒不安全主要體現在resize時的死迴圈及使用迭代器時的fast-fail上。 注:本章的程式碼均基於JDK 1.7.0_67 HashMap工作原理 HashMap資料結構

從jvm角度java執行

最近在學習jvm,發現隨著對虛擬機器底層的瞭解,對java的多執行緒也有了全新的認識,原來一個小小的synchronized關鍵字裡別有洞天。決定把自己關於java多執行緒的所學整理成一篇文章,從最基礎的為什麼使用多執行緒,一直深入講解到jvm底層的鎖實現。 多執行緒的目的 為什麼要使用多執

JAVA執行wait與notify詳細解析(生產者消費者案例引出)

生產者和消費者這個關係是個經典的多執行緒案例。現在我們編寫一個Demo來模擬生產者和消費者之間的關係。 假如有兩個類,一個是資料生產者類DataProvider,另一個是資料消費者類DataConsumer,這兩個類同時對資料類Data進行操作,生產者類負責生產資料,消費者類負責消費資料,下面是

JAVA 執行生產者消費者模式)

在生產-消費模式中:通常由兩類執行緒,即若干個生產者的執行緒和若干個消費者的執行緒。生產者執行緒負責提交使用者請求,消費者執行緒則負責具體處理生產者提交的任務,在生產者和消費者之間通過共享記憶體快取區進行通訊。 主要構成: provider:生產者執行緒負責生產資料 consume

Java執行程式設計實戰》——第七章Producer-Consumer(生產者消費者)模式

Producer-Consumer模式的核心是通過通道對資料(或任務)的生產者和消費者進行解耦,從而使二者的處理速率相對來說互不影響。 類圖 BlockingQueueChannel: 當佇列滿時,將當前執行緒掛起直到佇列非滿 當佇列為空時,將當前執行緒掛起直到佇列

Java執行基礎之手撕生產者消費者模式

問題描述 資料結構: 生產者/消費者 快取區(共享資源) 規則: 生產/消費者同時操作快取區。 當快取區為空的時候,消費者不能消費,即消費者阻塞。 當快取區為滿的時候,生產者不能生產,即生產者阻

Java執行2.4.生產者消費者之間的關係3

生產者與消費者之間的關係 1、執行緒間通訊舉例的問題解決2 (1)建立學生類 package cn.itcast_05; public class Student { String name; int age; boolean flag; // 預設情況是沒有

結合生活,剖析《生產者消費者模型》-java執行(一)

  部落格園的園友們好,看部落格園上各位大佬的文章,已陪伴了我程式設計師職業的三年, 如今自己同樣希望能把自己從小白到菜鳥的成長過程分享給大家。不定期更新!!! 首先我本人智商不高,理解問題十分吃力,完全不屬於天才的行列,因此學習每一個知識 都喜歡刨根問底,結合生活,徹徹底底理解知識的本質! 進入正題,這篇文

java執行 kfc 生產者消費者問題

package threadpractice.practice2; public class KFC{ volatile static int num = 0; public KFC() { } public void producer() { synchronized (this) { while

Java執行-生產者消費者模式

問題描述 有一群生產者程序在生產產品,並將這些產品提供給消費者程序去消費。為使生產者程序與消費者程序能併發執行,在兩者之間設定了一個具有n個緩衝區的緩衝池,生產者程序將它所產生的產品放入緩衝區中,消費者程序可以從一個緩衝區中取走產品去消費。儘管所有的生產者和消費

JAVA執行】如何解決一個生產者消費者問題

                             如何解決一個生產者與消費者問題 生產者與消費者問題是多執行緒同步的一個經典問題。生產者和消費者同時使用一塊緩衝區,生產者生產商品放入緩衝區,消費者從緩衝區中取出商品。我們需要保證的是,當緩衝區滿時,生產者不可生產商品

Java執行學習筆記(九) 生產者/消費者模式實現

1. 一個生產者和一個消費者:操作值 1.1 公共值 public class ValueObject { public static String value = ""; } 1.2 生產者 public class Producer {

Java執行-----實現生產者消費者模式的幾種方式

   1 生產者消費者模式概述      生產者消費者模式就是通過一個容器來解決生產者和消費者的強耦合問題。生產者和消費者彼此之間不直接通訊,而通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用等待消費者處理, 直接扔給阻塞佇列,消費者不找生產者要資料,

Java執行生產者消費者等待喚醒機制(示例)

在下面新建的兩條執行緒,兩條執行緒操作的物件都是學生類,一條執行緒生產學生物件的資料,一條執行緒消費學生物件的資料,且做到,有資料才消費,沒資料就等待,沒資料就生產,有資料就等待。 第一個案例是學生類物件,非常的簡單就定義了兩個成員變數,以及一個用於喚醒執行緒的標記。 成員變數預設會賦值

java執行-生產者消費者模型(有限緩衝問題)

文章目錄 @[toc] 1.預備知識點 2.問題描述 3.java實現方式的預備知識 4.實現 1.預備知識點 執行緒同步 同步就是協同步調,按預定的先後次序進行執行。如:你說完,我再說。“同

入坑JAVA執行併發(五)生產者消費者模式

生產者消費者模式對於理解多執行緒是一個很經典,也很好的例子 資源類: class Resource{ //資源初始化個數 private int init; //資源最大個數 private int Max; p

JAVA執行之——經典面試消費者生產者

用wait與notify、notifyAll 實現生產者與消費者 關於多執行緒的生產者與消費者有多種方式實現。目前用學過的wait、notifyAll來實現。程式碼: public class ThreadTest6 { static class

Java執行生產者消費者問題:使用synchronized 關鍵字解決生產者消費者問題

        今天看了一片博文,講Java多執行緒之執行緒的協作,其中作者用程式例項說明了生產者和消費者問題,但我及其他讀者發現程式多跑幾次還是會出現死鎖,百度搜了下大都數的例子也都存在bug,經過仔細研究發現其中的問題,並解決了,感覺有意義貼出來分享下。        

JAVA 執行經典案例-生產者消費者模型【使用wait/notify實現】

  生產者消費者模型實現細節 生產者生產產品到公共倉庫,消費者消費公共倉庫中產品。 情況一:當公共倉庫產品達到倉庫容量上限,生產者停止生產; 情況二:當公共倉庫沒有產品,或達到設定的倉庫容量下限,消費者停止消費; 情況三:當公共倉庫產品達到容量上限時,消費者消費一