我在 java 中做生產者消費者問題,但我的代碼卡在System.out.println("In condition in produce method " )這一行。我認為由于我的代碼不能執行consume method. 那么任何人都可以幫我解決這個問題并告訴我這背后的原因是什么以及應該在代碼中進行哪些修改。
import java.util.LinkedList;
class Consumer extends Thread {
public void run()
{
try{
PC p = PC.getInstance();
p.consume();
Thread.sleep(500);
}
catch(Exception e ){
System.out.println(e);
}
}
}
class Producer extends Thread{
public void run (){
PC p = PC.getInstance();
try{
p.produce();
Thread.sleep(500);
}
catch(Exception e){
System.out.println("interrupted");
}
}
}
class PC {
LinkedList a = new LinkedList();
int capacity = 2;
private static PC single_instance = null;
public static PC getInstance()
{
if (single_instance == null)
single_instance = new PC();
return single_instance;
}
public void consume() throws InterruptedException{
while (true) {
synchronized (this) {
while (a.size() == 0) {
System.out.println("here I am ");
wait();
}
int val = (int) a.removeFirst();
System.out.println("consumer consumed" val);
notify();
Thread.sleep(500);
}
}
}
public void produce() throws InterruptedException {
while(true) {
int value = 0;
synchronized (this) {
while (a.size() == capacity) {
System.out.println("In condition in produce method " );////
wait();
}
System.out.println("producing value " value);
a.add(value );
notify();
System.out.println("after notify in produce method" );
Thread.sleep(500);
}
}
}
}
public class multithreading {
public static void main(String[] args) throws InterruptedException {
Producer p1 = new Producer();
// Producer p2 = new Producer();
Consumer c1 = new Consumer();
p1.start();
c1.start();
p1.join();
c1.join();
}
}
我只得到輸出
producing value 0
after notify in produce method
producing value 0
after notify in produce method
In condition in produce method
Process finished with exit code 130
uj5u.com熱心網友回復:
這是不好的:
synchronized(this) {
...
Thread.sleep(...);
...
}
這很糟糕,因為正在休眠的執行緒無緣無故地將其他執行緒鎖定在臨界區之外。這就像,兩個室友共用一輛汽車,但其中一個室友拿了鑰匙然后上床睡覺。為什么在第一個室友睡覺的時候不允許另一個室友使用汽車?
這也很糟糕:
while (true) {
synchronized(this) {
...
}
}
這很糟糕,因為執行緒在離開臨界區后所做的下一件事就是嘗試重新進入臨界區。Java 的內在鎖是不公平的。剛剛離開同步塊的執行緒在嘗試重新進入時已經在運行。另一個執行緒被阻塞等待輪到它。在那種情況下,作業系統總是會選擇已經在運行的執行緒,因為在架構良好的程式中——即,在一個室友不拿著車鑰匙上床睡覺的程式中——通常會采用這種策略產生最佳性能。
將System.out.println()呼叫和Thread.sleep()呼叫移出synchronized(this)塊,這將使另一個執行緒有更好的運行機會:
while (true) {
synchronized(this) {
...
notify();
}
System.out.println("...");
Thread.sleep(500);
}
@Gardener 可能已經發現了您的問題:您的單例不是執行緒安全的(請參閱上面的 Gardener 評論)。您應該在某些靜態物件上同步靜態 getInstance() 方法。(PC 類物件可以作業。)
public static PC getInstance()
{
synchronized(PC.class) {
if (single_instance == null) {
single_instance = new PC();
}
return single_instance;
}
}
這不是很好:
...
catch (Exception e) {
System.out.println(e); // not great
System.out.println("interrupted"); // even less great
}
這不是很好,因為如果發生例外,它只會為您提供最少的資訊。這樣做是為了獲得關于標準錯誤輸出流的詳細訊息,該訊息準確地說明例外發生的位置:
...
catch (Exception e) {
e.printStackTrace();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/486653.html
