簡體   English   中英

Producer Consumer應用程序上的Java多線程查詢

[英]Java multithreading queries on Producer Consumer application

我編寫了一個簡單的Java多線程程序。

我對代碼有一些疑問。 請幫助我解決這些問題。

提前致謝!

這是我的代碼:

Producer.java

package com.prodcon;
import java.util.Stack;
public class Producer extends Thread {
    DataStorage data;
    MainProcess tempmp;
    public Producer(DataStorage dst, MainProcess mp){
        data = dst;
        tempmp = mp;
    }
    public void run(){
        for(int i = 0; i < 3; i++){
            System.out.println("Thread:"+this.getName()+"called");
            data.PutData();
            /*-------------current states---------------------*/
            System.out.println("Current states of the threads:");
            System.out.println("p1->"+tempmp.p1.getState());
            System.out.println("p2->"+tempmp.p2.getState());
            System.out.println("p3->"+tempmp.p3.getState());
            System.out.println("c1->"+tempmp.c1.getState());
            System.out.println("c2->"+tempmp.c2.getState());
            System.out.println("c3->"+tempmp.c3.getState());
            /*-------------current states---------------------*/

        }
    }
}

消費者.java

  package com.prodcon;

    public class Consumer extends Thread {
        DataStorage data;
        MainProcess tempmp;
        public Consumer(DataStorage dst, MainProcess mp){
            data = dst;
            tempmp = mp;
        }
        public void run(){
            for(int i = 0; i < 3; i++){
                System.out.println("Thread:"+this.getName()+"called");
                data.GetData();
                /*-------------current states---------------------*/
                System.out.println("Current states of the threads:");
                System.out.println("p1->"+tempmp.p1.getState());
                System.out.println("p2->"+tempmp.p2.getState());
                System.out.println("p3->"+tempmp.p3.getState());
                System.out.println("c1->"+tempmp.c1.getState());
                System.out.println("c2->"+tempmp.c2.getState());
                System.out.println("c3->"+tempmp.c3.getState());
                /*-------------current states---------------------*/
            }
        }
    }

數據存儲

    package com.prodcon;

import java.util.Random;
import java.util.Stack;

import javax.xml.crypto.Data;

public class DataStorage {

    int countofdata;
    Stack<Double> data;

    public DataStorage() {
        countofdata = 0;
        data = new Stack<Double>();
    }

    public synchronized void GetData() {
        while (data.isEmpty()) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
            }

        }
        double temp = (double) data.pop();
        //System.out.println("Data poped out:" + temp);
        countofdata++;
        notifyAll();
    }

    public synchronized void PutData() {
        while (true) {
            if (data.size() == 3) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
        double temp = Math.random();
        data.push(temp);
        //System.out.println("Data inserted in storage:" + temp);
        countofdata--;
        notifyAll();
    }
}

MainProcess.java

    package com.prodcon;

public class MainProcess {

    /**
     * @param args
     */
    DataStorage ProcessData;
    public Producer p1, p2, p3, p4;
    public Consumer c1, c2, c3, c4;
    public MainProcess(){
        ProcessData = new DataStorage();
        p1 = new Producer(ProcessData, this);
        p2 = new Producer(ProcessData, this);
        p3 = new Producer(ProcessData, this);
        c1 = new Consumer(ProcessData, this);
        c2 = new Consumer(ProcessData, this);
        c3 = new Consumer(ProcessData, this);
        p1.setName("p1");
        p2.setName("p2");
        p3.setName("p3");
        c1.setName("c1");
        c2.setName("c2");
        c3.setName("c3");
    }
    public void startprocess(){
        p1.start();
        p2.start();
        p3.start();
        c1.start();
        c2.start();
        c3.start();
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MainProcess mp1 = new MainProcess();
        mp1.startprocess();

    }

}

這是此程序的輸出:

    Thread:p2called
Thread:p3called
Current states of the threads:
Thread:p1called
Current states of the threads:
Thread:c3called
Current states of the threads:
p1->RUNNABLE
p2->BLOCKED
p3->RUNNABLE
c1->BLOCKED
c2->BLOCKED
c3->BLOCKED
Thread:p3called
Current states of the threads:
p1->RUNNABLE
p2->BLOCKED
p3->RUNNABLE
c1->BLOCKED
c2->BLOCKED
c3->BLOCKED
Thread:p3called
Thread:c2called
Thread:c1called
Current states of the threads:
Current states of the threads:
p1->RUNNABLE
Current states of the threads:
p2->BLOCKED
p1->RUNNABLE
p2->BLOCKED
p3->BLOCKED
c1->BLOCKED
c2->BLOCKED
c3->BLOCKED
Thread:p1called
Current states of the threads:
p1->RUNNABLE
p2->BLOCKED
p3->BLOCKED
c1->BLOCKED
c2->BLOCKED
c3->BLOCKED
Thread:p1called
Current states of the threads:
p1->RUNNABLE
p2->BLOCKED
p3->BLOCKED
c1->RUNNABLE
c2->RUNNABLE
c3->BLOCKED
Thread:c1called
Current states of the threads:
p1->BLOCKED
p2->BLOCKED
p3->BLOCKED
c1->RUNNABLE
c2->RUNNABLE
c3->BLOCKED
Thread:c1called
Current states of the threads:
p1->BLOCKED
p2->BLOCKED
p3->BLOCKED
c1->RUNNABLE
c2->RUNNABLE
c3->BLOCKED
Current states of the threads:
p1->RUNNABLE
p2->BLOCKED
p3->BLOCKED
c1->TERMINATED
c2->RUNNABLE
c3->BLOCKED
p1->RUNNABLE
p2->BLOCKED
p3->BLOCKED
c1->TERMINATED
c2->BLOCKED
c3->RUNNABLE
Thread:c3called
Current states of the threads:
p1->TERMINATED
p2->BLOCKED
p3->BLOCKED
c1->TERMINATED
c2->BLOCKED
c3->RUNNABLE
Thread:c3called
Current states of the threads:
p1->TERMINATED
p2->BLOCKED
p3->BLOCKED
c1->TERMINATED
c2->BLOCKED
c3->RUNNABLE
p3->RUNNABLE
p1->BLOCKED
p2->RUNNABLE
p3->RUNNABLE
c1->TERMINATED
c2->BLOCKED
c3->TERMINATED
Thread:p2called
Current states of the threads:
p1->TERMINATED
p2->RUNNABLE
p3->RUNNABLE
c1->TERMINATED
c2->BLOCKED
c3->TERMINATED
Thread:p2called
Current states of the threads:
p1->TERMINATED
p2->RUNNABLE
p3->RUNNABLE
c1->TERMINATED
c2->BLOCKED
c3->TERMINATED
p1->TERMINATED
p2->TERMINATED
p3->RUNNABLE
c1->TERMINATED
c2->RUNNABLE
c3->TERMINATED
Thread:c2called
Current states of the threads:
p1->TERMINATED
p2->TERMINATED
p3->RUNNABLE
c1->TERMINATED
c2->RUNNABLE
c3->TERMINATED
Thread:c2called
Current states of the threads:
p1->TERMINATED
p2->TERMINATED
p3->RUNNABLE
c1->TERMINATED
c2->RUNNABLE
c3->TERMINATED
c1->TERMINATED
c2->TERMINATED
c3->TERMINATED

我的問題是:

1.根據程序,這個過程永遠不會停止...但是然后一些線程會自動終止,為什么?

2.即使在詢問了一些線程進入等待狀態之后,也沒有線程根據輸出結果進入等待狀態。 為什么以及如何?

3.根據此代碼:生產者-消費者問題和讀寫器問題之間有什么區別?

再次感謝!!

第一和第二個問題-由於邏輯,該代碼自然退出。 嘗試在此處添加調試輸出,以查看生產者何時退出。

if (data.size() == 3) {
    try {
        wait();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
} else {
    System.out.printf("%s: breaking as data size is %d, %d%n", Thread.currentThread().getName(), countofdata, data.size());

    break;
}

另一個可能的問題是:

for(int i = 0; i < 3; i++){
    data.PutData();
}

您只將3次放入隊列。

提示:Java中生產者-消費者問題的經典實現是LinkedBlockingQueue

第三個問題。 我將嘗試與生產者和消費者進行解釋。 讀者-作家問題是當您沒有生產者,但有許多消費者訪問單個共享資源時。 其中一些可以讀取資源,而有些可以寫入資源。 可以同時讀取,並且寫鎖是獨占的。

UPDATE

要模擬多個讀取,您可以嘗試使用

  • LinkedBlockingQueue非常適合您的DataStorage
  • ReentrantReadWriteLock
  • 或更新您的解決方案。 這是學習示例,我沒有測試,但是應該給您大致的想法:
final Object readLock = new Object();      //use objects as locks
final Object writeLock = new Object();
public void GetData() {
    synchronized (readLock) {             // acquire only the read lock
        while (data.isEmpty()) {
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
            }

        }
        double temp = (double) data.pop();
        //System.out.println("Data poped out:" + temp);
        countofdata++;
        System.out.printf("%s: %d, %d%n", Thread.currentThread().getName(), countofdata, data.size());
        notifyAll();        
     }
 }

public void PutData() {
    synchronized (readLock) {       //first, acquire the read lock
        synchronized (writeLock) {  // then acquire the write lock
            while (true) {
                if (data.size() == 3) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } else {
                    System.out.printf("%s: breaking as data size is %d, %d%n", Thread.currentThread().getName(), countofdata, data.size());

                    break;
                }
            }
            double temp = Math.random();
            data.push(temp);
            //System.out.println("Data inserted in storage:" + temp);
            countofdata--;
            notifyAll();
        }
    }
}

我可以看到您非常熱衷於使用線程,這是問題的主題,但是您是否考慮過Observer / Observable?

數據存儲是您可觀察的。

消費者是觀察者。 他們正在尋找改變。

我是這樣修改您的代碼的,只有一個線程定期運行。

制片人:

 public class Producer{
    DataStorage data;
    MainProcess tempmp;

    public Producer(DataStorage dst, MainProcess mp){
        data = dst;
        tempmp = mp;
    }
    public void changeTheData(){

            data.PutData();
            System.out.println("INFO :: Producer :: Just put data");
    }
}

消費者:

 import java.util.Observable;
 import java.util.Observer;
 import java.util.Stack;
 import java.util.concurrent.atomic.AtomicReference;

 public class Consumer implements Observer {
    DataStorage data;
    MainProcess tempmp;
    public Consumer(DataStorage dst, MainProcess mp){
        data = dst;
        tempmp = mp;
    }


 public void update(Observable arg0, Object arg1) {
    System.out.println("INFO :: class is " + arg1.getClass().toString());
    System.out.println("INFO :: Consumer :: data is " + ((AtomicReference<Double>)arg1).get());


}
}

數據存儲:

 import java.util.Observable;
 import java.util.concurrent.atomic.AtomicReference;

 public class DataStorage extends Observable {

   int countofdata;
   AtomicReference<Double> data = new AtomicReference<Double>();

   public DataStorage() {
       countofdata = 0;

   }

   public AtomicReference<Double> GetData() {

       // System.out.println("Data poped out:" + temp);
       countofdata--;
       return data;

   }

   public synchronized void PutData() {

      this.data.set(Math.random());
      System.out.println("INFO :: DataStorage :: Data inserted in storage:" + this.data.get());
      this.setChanged();
      this.notifyObservers(data);
      countofdata++;

  }
 }

主流程:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainProcess implements Runnable{

/**
 * @param args
 */
DataStorage processData;
private ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);
private Producer p1, p2, p3, p4;
private Consumer c1, c2, c3, c4;

public MainProcess(){

    processData = new DataStorage();
    p1 = new Producer(processData, this);
    p2 = new Producer(processData, this);
    p3 = new Producer(processData, this);
    c1 = new Consumer(processData, this);
    c2 = new Consumer(processData, this);
    c3 = new Consumer(processData, this);
    processData.addObserver(c1);
    processData.addObserver(c2);
    processData.addObserver(c3);


}
public void startprocess(){
     this.scheduledExecutorService.scheduleAtFixedRate(this, 5, 10, TimeUnit.SECONDS);

}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    MainProcess mp1 = new MainProcess();
    mp1.startprocess();

}
public void run() {
    System.out.println("INFO :: p1 Changing the data");
    p1.changeTheData();
    System.out.println("INFO :: p2 Changed the data");
    p2.changeTheData();
    System.out.println("INFO :: p3 Changed the data");
    p3.changeTheData();
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM