如何在Java中当现有线程崩溃时创建新线程

huangapple go评论124阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2023年4月13日 21:25:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76005990.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定