2017-06-29 60 views
-4

語言點,這基本上決定了它的進一步執行。因爲我不想弄亂來自多個線程的輸出問題,會出現在固定的速率(另外稱爲主線程)另一個任務/線程運行(單),它可以用來獲取問題,並把它顯示給用戶。線程提出的問題數量可能會有所不同,一旦問題得到迴應,就不再需要。推薦數據結構的這種使用情況

此時我的當前實現使用LinkedTransferQueue,基本上讓我不必等待投票共享主線程和線程問題之間的數據。

我創建了一個Task類的同步ArrayList,每個類都包含一個LinkedTransferQueue<String>。線程創建了新Task,並增加了它的問題納入其隊列transfer()方法。主線程選取它們並獲得來自用戶的響應,該用戶返回到相同的隊列。這樣做的優點是LinkedTransferQueue提供了一個take()方法,讓我等無投票。

其它方法包括使用volatile shared變量,其值由主線程更新,並不斷被其他線程輪詢。

請建議如果任何其他數據結構可用於這種用途的情況。根據我的理解,這不完全是生產者 - 消費者問題。如果您有其他問題,請提問。

謝謝!

+0

我不明白廣度的原因。你能否說明理由,以便我可以照顧未來的問題? 我從Andreas得到了一個完全適合我的答案! – LearningToCode

回答

0

由於您希望線程等待答案,我建議創建一個問題對象,其中包含問題文本,可以存儲答案,並有一個CountDownLatch用於跟蹤答案是否可用。然後

public final class Question { 
    private final String question; 
    private String   answer; 
    private CountDownLatch latch = new CountDownLatch(1); 

    public Question(String question) { 
     this.question = question; 
    } 
    public String getQuestion() { 
     return this.question; 
    } 
    public String getAnswer() throws InterruptedException { 
     this.latch.await(); 
     return this.answer; 
    } 
    public void setAnswer(String answer) { 
     this.answer = answer; 
     this.latch.countDown(); 
    } 
} 

您的工作線程可以發送問題到主Queue,並等待答案,例如然後

public final class Worker implements Runnable { 
    private final Queue<Question> queue; 
    private final int    delayInSeconds; 
    private final String[]  questions; 

    public Worker(Queue<Question> queue, int delayInSeconds, String... questions) { 
     this.queue = queue; 
     this.delayInSeconds = delayInSeconds; 
     this.questions = questions; 
    } 
    @Override 
    public void run() { 
     List<String> answers = new ArrayList<>(); 
     try { 
      for (String question : this.questions) { 
       Thread.sleep(this.delayInSeconds * 1000L); 
       Question q = new Question(question); 
       this.queue.add(q); 
       String answer = q.getAnswer(); 
       answers.add(answer); 
      } 
     } catch (InterruptedException unused) { 
      System.out.println("Interrupted"); 
     } 
     System.out.println(answers); 
    } 
} 

主線程將使用某種BlockingQueue等待的問題,並給他們一次處理,例如一個像這樣:

public static void main(String[] args) throws Exception { 
    BlockingQueue<Question> queue = new LinkedBlockingQueue<>(); 
    Worker w1 = new Worker(queue, 3, "Can you play poker?", 
            "Can you juggle?", 
            "Can you summersault?"); 
    Worker w2 = new Worker(queue, 4, "How old are you?", 
            "How tall are you?"); 
    new Thread(w1).start(); 
    new Thread(w2).start(); 
    Scanner in = new Scanner(System.in); 
    for (int i = 0; i < 5; i++) { 
     Question q = queue.take(); 
     System.out.println(q.getQuestion()); 
     String answer = in.nextLine(); 
     q.setAnswer(answer); 
    } 
} 

樣本輸出

Can you play poker? 
yes 
How old are you? 
13 
Can you juggle? 
no 
How tall are you? 
5 11 
Can you summersault? 
[13, 5 11] 
no 
[yes, no, no] 
+0

'CountDownLatch'比我採取的方法更清潔,無需持續輪詢。大!! – LearningToCode