英文:
How to create a new thread when an existing one crashes in java
问题
以下是翻译好的部分:
我必须维护一系列的Java线程类,这些类存在于遗留代码中。
这些线程是通过Spring初始化在Web服务器启动时创建的。
它们的运行方法具有一个无限循环,循环中进行的工作可能会抛出一些异常(例如,因为数据库无法访问而引发的SQL连接异常)。
类似这样:
public class MyThread extends Thread implements InitializingBean {
...
@Override
public void run() {
try {
while(true) {
// 进行工作
}
}
catch (final SQLException se) {
// 进行一些错误处理
}
finally {
// 清理资源
}
}
}
上述代码的问题是,如果发生异常,线程就会结束。我希望线程要么保持存活,要么创建一个新线程并重试。
在这里的最佳实践是什么?
是创建一个新的线程吗?
我该如何做到这一点?
英文:
I have to maintain a series of java thread classes in legacy code.
The threads are created through spring initialization at startup of a web server.
Their run method have an infinite loop and work done in the loop
can throw a few exceptions (sql connection exceptions for example because the db is unreachable say)
Something like this
public class MyThread extends Thread implements InitializingBean {
...
@Override
public void run() {
try {
while(true) {
// do work
}
}
catch (final SQLException se) {
// do some error handling
}
finally {
// clean up resources
}
}
}
The problem with the above code is that if there is an exception the thread ends. I would like the thread to either stay alive or create a new thread and try again.
What is the best practice here?
To create a new Thread?
How would I do that?
答案1
得分: 2
No, just wrap a while (true) {}
around it. If you really do need abilities to programmatically end this thread permanently, you'd use while (!Thread.interrupted()) {}
instead and ensure you return (i.e. end the thread) in the catch (InterruptedException e) {}
block. Then, simply call .interrupt()
on your thread to eventually kill it (an interruption results in either that Thread.interrupted()
returning true exactly once, or an InterruptedException. Hence, ensure you break off your thread either way.
英文:
No, just wrap a while (true) {}
around it. If you really do need abilities to programmatically end this thread permanently, you'd use while (!Thread.interrupted()) {}
instead and ensure you return (i.e. end the thread) in the catch (InterruptedException e) {}
block. Then, simply call .interrupt()
on your thread to eventually kill it (an interruption results in either that Thread.interrupted()
returning true exactly once, or an InterruptedException. Hence, ensure you break off your thread either way.
答案2
得分: 1
你可以尝试使用单线程池并向池中提交一个可运行任务。如果发生异常,当前线程将被终止并创建一个新线程。
ExecutorService executorService = Executors.newSingleThreadExecutor();
英文:
You could try the single thread pool and submit a runnable task to the pool. If an exception occurs the current thread gets terminated and a new one is created.
ExecutorService executorService = Executors.newSingleThreadExecutor();
答案3
得分: 1
I'd like the thread to either stay alive or create a new thread and try again喵.
(A) To stay alive, add an outer while
loop as discussed in Answer by rzwitserloot.
(B) To get the effect of starting again, an alternative to starting a new thread is to rewrite your code to use the Executors framework added to Java 5. In modern Java, we rarely address the Thread
class directly.
Write your task as a class implementing Runnable
. Add a constructor that takes an ExecutorService
object as an argument.
class DatabaseReporter implements Runnable
{
private final ExecutorService executerService ;
DatabaseReporter ( final ExecutorService es ) {
this.executerService = es ;
}
@Override
public void run() {
try {
while(true) {
// do work
}
}
catch (final SQLException se) {
// do some error handling
}
finally {
// clean up resources
// clean up any ThreadLocal uses.
this.executorService.submit( new DatabaseReporter( this.executorService ) ) ;
}
}
}
Obtain a single-threaded executor service by calling Executors.newSingleThreadExecutor()
.
Keep a reference to your executor service. You must perform a graceful shutdown of your executor service before your app ends. Otherwise, your backing thread pool may continue indefinitely like a zombie 🧟♂️. Or, if in a Jakarta EE environment, use a managed executor service.
Beware of any use you may have made of ThreadLocal
. Since an executor service recycles threads, any previously set ThreadLocal
values remain.
In the future, when Project Loom succeeds, Java will gain virtual threads. When using virtual threads, the issue of leftover ThreadLocal
goes away.
英文:
>I would like the thread to either stay alive or create a new thread and try again.
(A) To stay alive, add an outer while
loop as discussed in Answer by rzwitserloot.
(B) To get the effect of starting again, an alternative to starting a new thread is to rewrite your code to use the Executors framework added to Java 5. In modern Java, we rarely address the Thread
class directly.
Write your task as a class implementing Runnable
. Add a constructor that takes an ExecutorService
object as an argument.
class DatabaseReporter implements Runnable
{
private final ExecutorService executerService ;
DatabaseReporter ( final ExecutorService es ) {
this.executerService = es ;
}
@Override
public void run() {
try {
while(true) {
// do work
}
}
catch (final SQLException se) {
// do some error handling
}
finally {
// clean up resources
// clean up any ThreadLocal uses.
this.executorService.submit( new DatabaseReporter( this.executorService ) ) ;
}
}
}
Obtain a single-threaded executor service by calling Executors.newSingleThreadExecutor()
.
Keep a reference to your executor service. You must perform a graceful shutdown of your executor service before your app ends. Otherwise your backing thread pool may continue indefinitely like a zombie 🧟♂️. Or, if in a Jakarta EE environment, use a managed executor service.
Beware of any use you may have made of ThreadLocal
. Since an executor service recycles threads, any previously set ThreadLocal
values remain.
In the future, when Project Loom succeeds, Java will gain virtual threads. When using virtual threads, the issue of leftover ThreadLocal
goes away.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论