Java 在没有主线程的情况下保持控制台输入活动?(爪哇)

Java 在没有主线程的情况下保持控制台输入活动?(爪哇),java,multithreading,server,system.in,console-input,Java,Multithreading,Server,System.in,Console Input,我正在用Java编写一个多线程的服务器。我构建了三个主要的活动线程,并从我的主方法开始: 例如,我的命令线程用于通过在控制台窗口中输入q来停止服务器。命令的运行方法定义如下: public void run(){ while(server.running.get()){ try{ String next = scan.nextLine(); if(next.equalsIgnoreCase("q")){

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

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

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=新ScannerSystem.in

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

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

Thread t1 = new Thread(server);
t1.start();
new Thread(time).start();
new Thread(commands).start();
try{
    t1.join();
}catch(Exception e){
    e.printStackTrace();   
}
现在回答我的问题。为什么控制台输入仅在主线程仍处于活动状态时才起作用?老实说,我不需要我的主线程了,所以让它终止就好了

在这里,仅仅定义没有名称的线程是否有什么不对的地方?我能够很好地终止每个线程,因为它们彼此交织在一起,除了我的命令线程之外,其他一切都正常工作

编辑: 我真的很感激所有关于解决这个问题的答案,但我真正想要的是为什么会发生这种情况的原因


服务器线程螺旋式关闭并完成自己的事情,即不断寻找新的连接并为这些连接建立新的环境,续订线程关闭并完成自己的事情,即在我使用google API时,这用于续订我的配额计数。除此之外,上面的代码让我明白了我在做什么

您应该让命令线程成为主线程。 在其他一切都启动后,将其放入main:

commands.run();

如果您希望主线程在不终止JVM的情况下终止,因此您可以使用守护进程线程

请查看此链接:


PS:请记住,拥有不终止的线程可能是危险的,特别是当它们使用资源时。

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

InputStream consoleInput = System.in;
System.setIn(new ByteArrayInputStream(new byte[0]));

在main离开时,我看不出从另一个线程读取有任何问题:

公共类IOWithoutMain{ 公共静态无效字符串[]args{ RuntimeMXBean runtime=ManagementFactory.getRuntimeMXBean; System.out.printf%s%s%s%s%n, runtime.getVmVendor, runtime.getVmName, System.getPropertyjava.version, runtime.getVmVersion; 新线程{ 公开募捐{ 试一试{ 睡一万个; System.out.printEnter输入:; InputStreamReader isr=新的InputStreamReaderSystem.in; BufferedReader br=新的BufferedReaderisr; System.out.printlnbr.readLine; }捕获中断异常| IOE异常{ e、 打印跟踪; } } }.开始; } } 控制台:

Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.8.0_60 (25.60-b23)
Enter input: Test
Test

等等,我很困惑,我的主线程是在上面没有连接的情况下终止的,还是在其他线程完成之前一直存在?如果它一直存在,那么为什么控制台输入不起作用呢?只有守护进程线程会使JVM终止。默认情况下,必须使用非守护进程线程使JVM保持活动状态。Logan是正确的。实际上我弄错了。JVM会在不等待守护进程正常完成的情况下杀死任何守护进程线程这是一个解决此问题的方法,但是您知道为什么当主线程结束时,is不能在单独的线程上工作吗?我相信它结束了。我们在您的代码中没有看到扫描引用生命周期。在从@LoganMzz读取之前,您不关闭System.in或扫描引用吗?请参见此处的关闭方法?这是扫描对象的关闭。如果服务器线程终止,我的服务器线程也可以关闭它。如果没有更多相关代码,任何人都无法提供帮助。@jtahlborn你在说什么?问题很简单,您不需要再看到代码,因为它与解释为什么在主线程完成其代码执行后控制台输入停止无关。如果我再添加一些代码,这会使我的观点变得混乱,根本不相关,因为这只是实现细节,而不是回答问题的必要条件。好吧,在我的框中对这个概念进行一个简单的测试,有一个单独的线程读取输入就可以了。我猜是你正在做的其他事情导致了这个问题。但是,您没有显示足够的其他内容,因此没有人可以帮助您找到问题;没有为我编译。此外,我必须这样做是没有意义的。IO流不应仅仅因为主静态方法线程完成其代码而停止。请使用Sysrem.setIn或Runtime.getRuntime.setIn。经典规则-谁打开,谁在行动中关闭-应用程序启动程序打开流,运行
s主方法,关闭流。事实上,这似乎是一种不正确的行为,您可以将其作为错误报告给JVM提供程序。我的控制台不接受用户的任何输入。此外,我测试了您的上述代码,但它不起作用。控制台停止接受任何输入。
Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 1.8.0_60 (25.60-b23)
Enter input: Test
Test