2013-04-26 264 views
3

我在爲架構編寫原型時遇到了一個奇怪的問題。爲什麼啓動一個線程被另一個線程阻塞?

我試着創建兩個獨立調度相同命令的線程。第一個線程是使用Scanner,第二個線程是依靠Swing。問題在於第一個線程阻止了第二個線程的啓動。第二個線程只有在掃描儀得到足夠的輸入後纔開始。強制第一個線程睡眠,直到第二個線程開始也暫時解決問題。

以下示例非常一致地重現了此行爲。睡在電話之間使得它更加一致。

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Scanner; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.WindowConstants; 

public final class Bug { 
    public static void main(final String[] arguments) { 
     new Thread(new Runnable() { 
      @Override 
      public void run() { 
       System.out.println("The commands are \"wait\" and \"quit\"."); 
       final Scanner scanner = new Scanner(System.in); 
       loop: while (true) { 
        System.out.print("Enter a command: "); 
        final String command = scanner.nextLine(); 
        switch (command.toLowerCase()) { 
        case "exit": 
        case "quit": 
         break loop; 
        default: 
         System.out.println("Use \"wait\" or \"quit\" instead of \"" + command + "\"."); 
        case "wait": 
        } 
       } 
       scanner.close(); 
      } 
     }).start(); 

     try { 
      Thread.sleep(1000);//improves consistency 
     } 
     catch (final InterruptedException exception) {} 

     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       final JFrame frame = new JFrame("Commands"); 
       frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
       frame.setResizable(false); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new JButton("Wait"), BorderLayout.LINE_START); 
       final JButton button = new JButton("Quit"); 
       button.addActionListener(new ActionListener() { 
        @Override 
        public void actionPerformed(final ActionEvent event) { 
         frame.dispose(); 
        } 
       }); 
       frame.add(button, BorderLayout.LINE_END); 
       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

爲什麼沒有第二個線程正常啓動?我該責怪嗎?

A similar problem是在十年前作爲錯誤提交的。


運行java -version結果

java version "1.7.0_21" 
Java(TM) SE Runtime Environment (build 1.7.0_21-b11) 
Java HotSpot(TM) Client VM (build 23.21-b01, mixed mode, sharing) 

cmd -info

Microsoft Windows XP [Version 5.1.2600] 
(C) Copyright 1985-2001 Microsoft Corp. 

如果該事項。

+0

我在上面發佈的代碼中沒有看到任何內容,可以解釋您描述的行爲。這對我來說是一個難題。 – 2013-04-26 20:49:18

+0

適用於我:Ubuntu 13.04; openjdk 1.7.0_21 – skirsch 2013-04-26 20:49:41

+0

我在Windows 7上試過這個代碼,jdk 1.7。有用。你的情況的問題是別的。 – CodeBlue 2013-04-26 20:50:38

回答

0

此代碼工作對我來說,雖然我已經通過一系列的if/else,如果(我使用的Java 1.6),以取代開關

final String command = scanner.nextLine().toLowerCase(); 
if (command.equals("exit") || command.equals("quit")) { 
    break loop; 
} else if (!command.equals("wait")) { 
    System.out.println("Use \"wait\" or \"quit\" instead of \"" + command + "\"."); 
} 
0

這可能是因爲你使用的EventQueue。 invokeLater()爲第二個線程。在線程啓動時,第一個線程可能已經在等待控制檯上的用戶輸入。我可以想象EventQueue可能不會立即觸發你的第二個線程,因爲第一個線程已經在等待輸入,因此堵塞了事件泵。

我建議你使用不同的機制來啓動第二個線程。爲什麼不開始就像你的第一個線程?

此外,我同意其他意見,這個代碼應該重構,以幫助更清楚發生了什麼事以及爲什麼。

相關問題