2013-04-26 268 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可能不会立即触发你的第二个线程,因为第一个线程已经在等待输入,因此堵塞了事件泵。

我建议你使用不同的机制来启动第二个线程。为什么不开始就像你的第一个线程?

此外,我同意其他意见,这个代码应该重构,以帮助更清楚发生了什么事以及为什么。

相关问题