You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何维持多线程Java/Scala应用运行?新手服务启动后进程退出求助

Hey there! Let's figure out why your process exits right away and fix it—this is a super common gotcha when working with threads in Scala/Java, so you’re already on the right track by looking into user vs daemon threads.

The Core Issue

JVM exits when all non-daemon (user) threads finish executing. If your main thread starts both services and then immediately completes (without waiting for the service threads to keep running), the JVM sees no active non-daemon threads left and shuts down with exit code 0.

Fixes to Keep Your Services Running

Here’s how to adjust your code to keep the process alive while both services run:

1. Ensure Your Service Threads Are Non-Daemon

By default, any Thread you create is a non-daemon thread—so unless you explicitly called setDaemon(true) on your service threads, this part is probably already covered. Double-check if any framework you’re using (like for the web server) sets threads to daemon by default, though.

2. Make the Main Thread Wait for Your Services

Your main thread is the first non-daemon thread to finish, which triggers the JVM shutdown. You need to make it block indefinitely (or until you intentionally shut down the app) to keep the process alive.

Let’s walk through a concrete Scala example:

Example Socket Subscriber Thread

First, your socket listener should run in a non-daemon thread with an infinite loop (to keep listening for connections):

import java.net.ServerSocket

class SocketSubscriber extends Runnable {
  override def run(): Unit = {
    val serverSocket = new ServerSocket(9999)
    println("Socket subscriber listening on port 9999...")
    
    // Infinite loop to accept connections (keeps the thread alive)
    try {
      while (true) {
        val clientSocket = serverSocket.accept()
        // Spin up a worker thread to handle the incoming message
        new Thread(new WorkerThread(clientSocket)).start()
      }
    } catch {
      case e: Exception => println(s"Socket subscriber error: ${e.getMessage}")
    } finally {
      serverSocket.close()
    }
  }
}

class WorkerThread(socket: java.net.Socket) extends Runnable {
  override def run(): Unit = {
    // Logic to process the message and start work goes here
    println(s"Handling connection from ${socket.getInetAddress}")
    // Don't forget to close the socket when done!
    socket.close()
  }
}
Example Web Server (Using Akka HTTP)

For the web server, most frameworks will manage their own threads, but you still need to ensure the main thread doesn’t exit:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Directives._

object StatusWebServer {
  def start()(implicit system: ActorSystem): Unit = {
    val statusRoute = path("worker-status") {
      get {
        // Logic to fetch and return worker thread status goes here
        complete("All worker threads are running!")
      }
    }
    Http().newServerAt("localhost", 8080).bind(statusRoute)
    println("Web server running on http://localhost:8080/worker-status")
  }
}
Main App to Tie It All Together

The key here is using join() on one of your long-running service threads to block the main thread:

import akka.actor.ActorSystem

object ServiceMain extends App {
  // Start socket subscriber thread
  val socketThread = new Thread(new SocketSubscriber())
  socketThread.start()

  // Start web server
  implicit val webSystem = ActorSystem("StatusWebServer")
  StatusWebServer.start()

  // Add a shutdown hook to clean up resources gracefully
  Runtime.getRuntime.addShutdownHook(new Thread(() => {
    println("\nShutting down services...")
    webSystem.terminate()
    // Add code to close the socket server if needed
  }))

  // Block the main thread indefinitely by waiting for the socket subscriber
  // Since the socket thread runs an infinite loop, this will keep the JVM alive
  socketThread.join()
}

Why This Works

  • socketThread.join() makes the main thread wait until the socket subscriber thread finishes. Since the socket thread runs an infinite loop (until an error or shutdown), the main thread will never exit on its own.
  • All service threads are non-daemon, so the JVM will wait for them to finish before shutting down.
  • The shutdown hook ensures you clean up resources (like the Akka ActorSystem or socket server) when you manually terminate the process (e.g., with Ctrl+C).

Quick Checks If It Still Exits

  • Verify none of your service threads are marked as daemon (check for setDaemon(true) calls).
  • Make sure your socket listener or web server isn’t throwing an uncaught exception that kills the thread (add try-catch blocks around critical logic).

内容的提问来源于stack exchange,提问作者CubemonkeyNYC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:53:23