0

I'm pretty new to Scala/Java and have to build a service that will have at least two sub-services running: a socket-based subscriber that listens for messages to kick off workers, and a web server that will serve a status page for those workers.

I can get these things to run, but after both start the whole process immediately exits with code 0.

I did some research to learn about user threads vs daemon threads in Java, as well as threading in general, so now my approach is basically this:

val webServerThread = new Thread(WebServer(config)).start()
val subscriberThread = new Thread(Subscriber(config)).start()
val aliveThread = new Thread(keepAlive(true)).start()

The third thread simply contains a while(true){} block to leave a user thread up.

There has to be a smarter way of doing this, but I don't know what it is and seems impossible to discover. How do http server's stay running, for example? Is there a while(true) loop underneath every framework out there?

Any help would be appreciated.

CubemonkeyNYC
  • 273
  • 3
  • 17
  • 1
    Threads are not daemon by default, so there's no reason for the keep alive task. – markspace Apr 04 '18 at 20:37
  • The real way to make a web service is to use a framework, like Java Enterprise Edition. However if you're totally new to Java you might want to look at O'Reilly's *Learning Java*. They have a chapter on networking which includes a small web server (Hint: they use a [Selector](http://www.baeldung.com/java-nio-selector)). – markspace Apr 04 '18 at 20:42
  • You can force the main thread to wait for each created thread to finish by calling that thread's `.join` method. – Mike Allen Apr 04 '18 at 20:46
  • `while(true){Thread.sleep(10000);}` would be a smarter way to keep a thread alive without doing any work. – Solomon Slow Apr 04 '18 at 21:09
  • @MikeAllen, that makes sense _if_ there is something that the main thread needs to do after all of the other threads have died. If not, then there's no point in having the main() thread hang around, occupying memory. – Solomon Slow Apr 04 '18 at 21:15
  • @markspace We're using http4s for the web server portion of the app. Making the service that runs the web server into a Runnable along with all the other pieces seems to have things going. The http4s web server I suppose just sits there and blocks the thread from exiting, so it's keeping the greater application alive. – CubemonkeyNYC Apr 04 '18 at 21:36
  • htt4s looks OK, but the Java servlet spec (what the docs say http4s replaces) is less than half a loaf of the JEE framework. Dependency injection probably accounts for the biggest boost in productivity. And your reply is weird, if your framework is using daemon threads for worker threads you could be in big trouble if your app shuts down abruptly. – markspace Apr 04 '18 at 23:01
  • @markspace I wouldn't be surprised if my reply is weird. My background is JS, Python, and C#. Still fumbling my way around Scala/Java. – CubemonkeyNYC Apr 05 '18 at 04:11
  • @MikeAllen, I am not familiar with the Scala language or, with how the standard Java libraries might behave differently when you're using Scala, but a JVM is not supposed to exit until _all_ of the non-daemon threads terminate. I have written plenty of pure Java programs that continue to run after the `main()` thread is gone. – Solomon Slow Apr 05 '18 at 13:20
  • @jameslarge So for all services that have to stay running, say a web server or something, is there some code somewhere that just is basically while(shouldRun) {//nothing} ? – CubemonkeyNYC Apr 06 '18 at 23:47

2 Answers2

2

The run() method of the thread would have to be an endless loop, until some condition occurs and you exit the loop.

To wait for a thread to exit, the way to do that is as follows:

final Runnable runnable = new Runnable() {
    public void run() {
        // do stuff
    }
};

final Thread thread = new Thread(runnable);
thread.start();
try {
    thread.join();
} catch (final InterruptedException e) {
    // deal with exception
}

Obviously, that will only wait for one thread. It depends on your scenario whether this makes sense. Alternatively, you could use a ThreadPoolExecutor, invoke the shutdown() or shutdownNow() method, and use awaitTermination for it to stop.

SeverityOne
  • 2,476
  • 12
  • 25
0

So for all services that have to stay running, say a web server or something, is there some code somewhere that just is basically while(shouldRun) {//nothing}?

No. There is never any reason to have a JRE thread that does nothing, and a thread that uses 100% CPU while accomplishing nothing would be even worse.

Pretty much every thread in a program should sit in a loop, waiting for something to do.* E.g., An I/O thread that waits to receive and process input from some external source, a pool thread that waits for tasks to perform, a scheduler thread that waits until it's time to perform the next scheduled task.

A web service must have at least one thread that sits in a loop and waits to handle incoming connections. I don't remember how to write that without doing some research first because there are so many open-source web servers out there: There's no reason to write your own except for practice. There is even one built-in to the Oracle JRE.** In pseudo code, it might look like this:

while (! time_to_shut_down) {
    connection = WaitForIncomingConnection();
    clientThreadPool.handle(connection);
}

I can get these things to run, but after both start the whole process immediately exits with code 0.

I do not know why your program won't stay running. I am not familiar with Scala or, with the WebServer class or the Subscriber class.

What is config? Maybe somebody would be able to help you if you would ammend your question to show how you create the configuration object.


*One exception to that rule would be a compute-thread in a program that performs a single, massive computation and then exits.

**See https://stackoverflow.com/a/3732328/801894. The server.start(); call in that example is what kicks off the service thread. And, notice that the main() thread terminates right after it starts the server thread.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57