0

I am writing a server in Java, which is multithreaded. I have three main active threads that I build and start from my main method:

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 */
        }
     }
}

My commands thread is used, for example, for stopping the server by have the input "q" into the console window. commands's run method is defined as so:

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.");
        }
    }
}

*Where scan is defined as: Scanner scan = new Scanner(System.in);

When I run my server all my threads work, except the commands thread as the console is not accepting inputs.

I then realized, if I waited for my server thread (this is the thread I most care about) to join up with my main (static method) thread, my commands thread then worked. Meaning the console accepted inputs if I changed my main method code to this:

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

Now to my question. Why does console input only work if the main thread is still active? I honestly do not need my main thread anymore, so letting it terminate would be just fine.

Is there something I am doing incorrectly here with just defining my threads without a name? I am able to terminate each thread nicely as they are interweaved with each other and everything works just except my commands thread.

EDIT: I really appreciate all of the answers regarding a fix to this issue but what I am really after is the reason of why this is happening.

The server thread spirals off and does it own thing (i.e. constantly looking for new connections and establishing new environments for those connections) and the renewal thread goes off and does its own thing as well (i.e. this is used for renewing my quota count as I am using a google API). Other than that, the above code gets the point across on what I am doing.

10
  • We don't see "scan" reference lifecycle in your code. Don't you close System.in or scan reference before reading from ? Commented Oct 6, 2015 at 23:20
  • @LoganMzz See the close() method there? That is the closing of the scan object. My server thread has the ability to close it too if it terminates. Commented Oct 6, 2015 at 23:59
  • 1
    without more relevant code, there's not much anyone can do to help. Commented Oct 7, 2015 at 0:14
  • @jtahlborn What are you talking about? The question is simple, you don't need to see anymore code as it is not relevant to explaining why after the main thread finishes executing its code that the console input stops. If I included anymore code it would clutter my point and is not relevant at all as it is just implementation details that are not imperative to answering the question. Commented Oct 7, 2015 at 17:24
  • Well, a simple test of the concept on my box has a separate thread reading input just fine. my guess is that something else you are doing is causing the issue. however, you aren't showing enough "else", therefore no one can help you find the problem. Commented Oct 7, 2015 at 17:34

4 Answers 4

1

You should have your commands thread be your main thread. Just put this in main() after everything else is started:

commands.run();
Sign up to request clarification or add additional context in comments.

1 Comment

That is a fix to this problem, but do you know why is doesn't work on a separate thread when the main thread ends (well I believe it ends)?
0

I don't see any problem with reading from another thread while main is gone away:

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();
  }
}

Console :

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

1 Comment

Well when I do do this it does not work. My console does not accept any inputs from the user. In addition, I tested your above code and it doesn't work. The console ceases to accepted any input.
-1

JVM takes care about main thread and IO streams. You can try to keep input stream intact by saving/hiding its actual value in the main thread (usual tests approach):

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

2 Comments

The line "System.in = new ByteArrayInputStream(new byte[0]);" does not compile for me. In addition, it doesn't make sense that I would have to do this. The IO stream should not stop just because the main (static method) thread finishes its code.
Use Sysrem.setIn() or Runtime.getRuntime().setIn(). Classic rule - "who open, that closes" in action - app starter opens streams, runs main method, closes streams. Indeed this seems to be an incorrect behavior and you can report it as bug to your JVM provider.
-2

If you want the main thread to terminate without terminating the JVM (and so your other threads) you can use the daemon threads.

Have a look at this link: What is Daemon thread in Java?

PS: remember that having threads which don't terminate can be dangerous especially when they use resources.

3 Comments

Wait I am confused, does my main thread terminate above (without the join()) or does it stay around until the other threads finish? If it stays around then why doesn't console input work?
Having only daemon threads make the JVM to terminate. You have to use "non-daemon" (by default) thread to make the JVM keep alive.
Logan is right. I actually got it wrong. The JVM would kill any daemon thread without waiting for them to finish gracefully

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.