2016-12-24 46 views
0

有兩種方法將消息推送到arraylist,其他方法從arraylist中檢索消息。兩種方法都是同步的。 我創建了兩個線程,一個將消息推送到arraylist和其他檢索。兩個線程都處於僵局situation.How來解決它兩個線程正在等待對方,無法解析

下面是推動代碼和顯示信息

public class FetchCurrentTime { 

    static final int MAXMESSAGE = 5; 
    private List<String> messages = new ArrayList<String>(); 

    public synchronized void putTime(){ 
     while(messages.size() != MAXMESSAGE){ 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 
      Calendar cal = Calendar.getInstance(); 
      messages.add(dateFormat.format(cal.getTime()).toString()); 
     } 
     notify(); 

    } 

    public synchronized String getTime(){ 
     String message= "Unable to fetch time"; 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     if(!message.isEmpty()){ 
     message = messages.remove(messages.size()-1); 
     } 
     notify(); 
     return message; 
    } 

} 

下面是生產者和消費者代碼

public class ProduceTime extends Thread { 
    FetchCurrentTime fc ; 

    public ProduceTime(FetchCurrentTime fc) { 
      this.fc = fc; 
    } 

    @Override 
    public void run() { 
     fc.putTime(); 
    } 

} 


public class ConsumeTime extends Thread { 
    FetchCurrentTime fc ; 
    public ConsumeTime(FetchCurrentTime fc) { 
     this.fc = fc; 
    } 

    @Override 
    public void run() { 
     while (true) { 
      String time = fc.getTime(); 
      System.out.println(time); 
     } 
    } 

} 

這裏是代碼去測試。

public class GetDate { 

    public static void main(String[] args) throws InterruptedException { 
     FetchCurrentTime fc = new FetchCurrentTime(); 
     ProduceTime p = new ProduceTime(fc); 
     ConsumeTime c = new ConsumeTime(fc); 

     Thread t1 = new Thread(p); 
     Thread t2 = new Thread(c); 

     t1.start(); 
     t2.start(); 
    } 

} 
+1

用文字描述你的'putTime'在做什麼。 –

+0

你在測試等待和通知方法嗎?現代Java代碼不使用通知和等待。在多線程應用程序中存在更高階的類和方法。 –

+0

@SotiriosDelimanolis putTime獲取當前時間並將時間添加到字符串的數組列表中。我使putTime和getTime方法同步,以便putTime將消息插入到arraylist中,getTime不應該從arraylist中檢索消息並顯示它 – Raghu

回答

0

我看到問題是在和putTime()中調用wait()時,因爲兩者都在等待另一方通知;永遠不會發生。 此外,還有在getTime()一個錯字,應該是messages.isEmpty()(列表),而不是message.isEmpty()(字符串)

你可以給這個代碼一試。請注意,它會永久運行,因此您需要處理終止條件。

public synchronized void putTime() { 

    while (true) { // To ensure list contains 5 elements at any point of time before removal 
     if (messages.size() >= MAXMESSAGE) { 
      try { 
       wait(); // wait issued only when list is full 
      } catch(InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     while (messages.size() < MAXMESSAGE) { 
      DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); 
      Calendar cal = Calendar.getInstance(); 
      messages.add(dateFormat.format(cal.getTime()).toString()); 
     } 

     notify(); // notify getTime() to resume execution 
    } 
} 

public synchronized String getTime() { 
    String message = "Unable to fetch time"; 

    try { 
     Thread.sleep(100); // adding delay to help see the output 

     if (messages.isEmpty()) { 
      wait(); // wait for putTime() to add messages to the list 
     } 

     if (!messages.isEmpty()) { 
      message = messages.remove(messages.size() - 1); 
      notify(); // notifies putTime() to add a message to the list; helps keep count to 5 
     } 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    return message; 
} 

也就是說,建議使用先進的線程結構,它有助於達到相同的(更容易),並具有更好的吞吐量。

希望這有助於:)

-1

有很多方法可以解決這個問題。任何時候有兩個或兩個以上的鎖被兩個線程以不同的訂單獲取時會發生死鎖。排序是關鍵部分。

E.g.如果一個線程可以獲取put lock,另一個獲得get lock,反之亦然,則會出現死鎖。如果每個線程總是首先獲取獲取鎖,然後放置鎖,並在釋放獲取鎖之前釋放放置鎖,則無法實現死鎖。

要解決此問題,請將鎖定爲顯式(例如:synchronized(lockObject){/ * code * /}),並且要麼始終獲取鎖定,要麼只使用一個鎖定。

另一種解決方案是使用像Akka這樣的actor框架。演員抽象出鎖定,特別適合發送和接收消息。通過一個actor,有一個「郵箱」可以同步訪問來添加來自其他線程的消息,但是actor本身在一個線程中串行處理消息。

+0

如果你打算倒票,可能想讓我知道爲什麼。 – Brian

+0

你一般在談論僵局,但不要解釋它是如何適用於他們的問題的。然後你出於某種原因帶入Akka。你完全錯過了這一點。關於這個問題的評論可以更好地描述這些問題。你可能想要把它們包含在你的答案中。 –

+0

具體問題是「兩個線程處於死鎖狀態,如何解決它。」要麼按順序獲取鎖,要麼使用akka,將會消除死鎖。我在回答問題時寫道,我不會爲他寫他的代碼。 – Brian