0

我正在用 Java 编写一个服务器,它是多线程的。我构建了三个主要的活动线程,并从我的main方法开始:

public class Run{
     public static void main(String[] args){
        try{
            /*
             *  Definition and initialization of "server," "time," and 
             *  "commands" variables not shown.
             */

            new Thread(server).start();
            new Thread(time).start();
            new Thread(commands).start();
        }catch(FileNotFoundException unfound){
            /* Exception code not shown */
        }catch(IOException ioe){
            /* Exception code not shown */
        }
     }
}

例如,我的命令线程用于通过在控制台窗口中输入“q”来停止服务器。commandsrun 方法定义如下:

public void run(){
    while(server.running.get()){
        try{
             String next = scan.nextLine();
             if(next.equalsIgnoreCase("q")){
                  server.shutdown();
                  close();
             }else
                  System.out.println(LocalDateTime.now() + " - Unknown command.");
        }catch(IOException ioe){
             System.out.println(LocalDateTime.now() + " - The commands thread has produced an exception.");
        }
    }
}

*其中扫描定义为:Scanner scan = new Scanner(System.in);

当我运行我的服务器时,我的所有线程都工作,除了命令线程,因为控制台不接受输入。

然后我意识到,如果我等待我的服务器线程(这是我最关心的线程)加入我的(静态方法)线程,我的命令线程就会工作。如果我将主要方法代码更改为以下内容,则意味着控制台接受输入:

Thread t1 = new Thread(server);
t1.start();
new Thread(time).start();
new Thread(commands).start();
try{
    t1.join();
}catch(Exception e){
    e.printStackTrace();   
}

现在我的问题。为什么控制台输入仅在线程仍处于活动状态时才有效?老实说,我不再需要我的线程,所以让它终止就可以了。

只是在没有名称的情况下定义了我的线程,我在这里做错了什么吗?我能够很好地终止每个线程,因为它们相互交织,并且除了我的命令线程之外一切正常。

编辑: 我非常感谢有关解决此问题的所有答案,但我真正追求的是发生这种情况的原因

服务器线程螺旋式下降并做自己的事情(即不断寻找新的连接并为这些连接建立新环境)并且更新线程关闭并做自己的事情(即这用于更新我的配额计数,因为我我正在使用谷歌 API)。除此之外,上面的代码说明了我在做什么。

4

4 回答 4

1

你应该让你的命令线程成为你的主线程。只需在其他所有内容启动后将其放入 main() :

commands.run();
于 2015-10-06T22:17:17.107 回答
0

当 main 消失时,我没有看到从另一个线程读取任何问题:

public class IOWithoutMain {

  public static void main(String[] args) {
    RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
    System.out.printf("%s %s %s (%s)%n",
        runtime.getVmVendor(),
        runtime.getVmName(),
        System.getProperty("java.version"),
        runtime.getVmVersion());
    new Thread() {
      public void run() {
        try {
          sleep(10_000);
          System.out.print("Enter input: ");
          InputStreamReader isr = new InputStreamReader(System.in);
          BufferedReader br = new BufferedReader(isr);
          System.out.println(br.readLine());
        } catch (InterruptedException|IOException e) {
          e.printStackTrace();
        }
      }
    }.start();
  }
}

安慰 :

Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.8.0_60 (25.60-b23)
Enter input: Test
Test
于 2015-10-06T23:17:26.583 回答
-1

JVM 负责主线程和 IO 流。您可以尝试通过在主线程中保存/隐藏其实际值来保持输入流的完整性(通常的测试方法):

InputStream consoleInput = System.in;
System.setIn(new ByteArrayInputStream(new byte[0]));
于 2015-10-06T23:07:09.517 回答
-2

如果您希望主线程终止而不终止 JVM(以及其他线程),您可以使用守护线程。

看看这个链接:什么是 Java 中的守护线程?

PS:请记住,拥有不终止的线程可能很危险,尤其是在它们使用资源时。

于 2015-10-06T22:33:53.670 回答