[英]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.