在 Java 中启动线程而不等待它们(使用 .join())是否危险?
当用java编写多线程互联网服务器时,主线程启动新的 并行处理传入请求。
如果主线程不等待(使用 .join()
)它们,有什么问题吗? (创建一个新线程然后等待它显然是荒谬的)。
我知道,在实际情况下,您应该(或“您必须”?)实施一个池 线程空闲时“重新使用”它们来处理新请求。
但对于小型应用程序,我们应该使用线程池吗?
When writing a multithread internet server in java, the main-thread starts new
ones to serve incoming requests in parallel.
Is any problem if the main-thread does not wait ( with .join()
) for them?
(It is obviously absurd create a new thread and then, wait for it).
I know that, in a practical situation, you should (or "you must"?) implement a pool
of threads to "re-use" them for new requests when they become idle.
But for small applications, should we use a pool of threads?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不需要等待线程。
它们可以自行完成运行(如果它们是为了执行一项特定任务而生成的),也可以无限期地运行(例如,在服务器类型的环境中)。
然而,它们应该处理中断并响应关闭请求。请参阅本文了解如何正确执行此操作。
如果您需要一组线程,我将使用池和 执行器方法,因为它们会为您管理线程资源。如果您正在编写一个多线程网络服务器,那么我会研究使用(比如说)servlet 容器或框架,例如 Mina 。
You don't need to wait for threads.
They can either complete running on their own (if they've been spawned to perform one particular task), or run indefinitely (e.g. in a server-type environment).
They should handle interrupts and respond to shutdown requests, however. See this article on how to do this correctly.
If you need a set of threads I would use a pool and executor methods since they'll look after thread resource management for you. If you're writing a multi-threaded network server then I would investigating using (say) a servlet container or a framework such as Mina.
您的方法中唯一的问题是它无法扩展到超出特定请求率。如果请求传入的速度快于服务器处理它们的速度,则线程数量将不断增加。由于每个线程都会增加一些开销并占用CPU时间,因此处理每个请求的时间会变长,因此问题会变得更糟(因为线程数量增加得更快)。最终,将无法再处理任何请求,因为所有 CPU 时间都被开销浪费了。您的应用程序可能会崩溃。
另一种方法是使用具有固定线程上限的线程池(这取决于硬件的能力)。如果请求多于线程能够处理的数量,则某些请求将不得不在请求队列中等待太长时间,并且会因超时而失败。但应用程序仍然能够处理其余的传入请求。
幸运的是,Java API 已经提供了一个很好且灵活的 ThreadPool 实现,请参阅 ThreadPoolExecutor。使用它可能比使用原始方法实现所有内容更容易,所以没有理由不使用它。
The only problem in your approach is that it does not scale well beyond a certain request rate. If the requests are coming in faster than your server is able to handle them, the number of threads will rise continuously. As each thread adds some overhead and uses CPU time, the time for handling each request will get longer, so the problem will get worse (because the number of threads rises even faster). Eventually no request will be able to get handled anymore because all of the CPU time is wasted with overhead. Probably your application will crash.
The alternative is to use a ThreadPool with a fixed upper bound of threads (which depends on the power of the hardware). If there are more requests than the threads are able to handle, some requests will have to wait too long in the request queue, and will fail due to a timeout. But the application will still be able to handle the rest of the incoming requests.
Fortunately the Java API already provides a nice and flexible ThreadPool implementation, see ThreadPoolExecutor. Using this is probably even easier than implementing everything with your original approach, so no reason not to use it.
Thread.join() 允许您等待线程结束,这与启动新线程时的预期相反。总之,您启动新线程来与原始线程并行执行操作。
仅当您确实需要等待生成的线程完成时,您才应该 join() 它。
Thread.join() lets you wait for the Thread to end, which is mostly contrary to what you want when starting a new Thread. At all, you start the new thread to do stuff in parallel to the original Thread.
Only if you really need to wait for the spawned thread to finish, you should join() it.
如果您需要线程的结果或需要执行一些清理操作(只有在所有线程都死掉后才可能进行),则应该等待线程,否则就不能。
对于线程池:只要有一些非固定数量的任务要运行,即数量取决于输入,我就会使用它。
You should wait for your threads if you need their results or need to do some cleanup which is only possible after all of them are dead, otherwise not.
For the Thread-Pool: I would use it whenever you have some non-fixed number of tasks to run, i.e. if the number depends on the input.
我想收集这个有趣的(对我来说)问题的主要想法。
我不能完全同意“你
不需要等待线程”。
只是在某种意义上,如果你不这样做
加入一个线程(并且没有
指向它的指针)一旦线程
完成后,其资源被释放
(对吗?我不确定)。
线程池的使用只是
避免开销所必需的
线程创建,因为...
你可以限制并行的数量
运行线程通过记帐,使用共享变量(并且没有线程池),然后有多少
已开始但尚未完成。
I would like to collect the main ideas of this interesting (for me) question.
I can't totally agree with "you
don't need to wait for threads".
Only in the sense that if you don't
join a thread (and don't have a
pointer to it) once the thread is
done, its resources are freed
(right? I'm not sure).
The use of a thread pool is only
necessary to avoid the overhead of
thread creation, because ...
You can limit the number of parallel
running threads by accounting, with shared variables (and without a thread pool), how many of then
were started but not yet finished.