Java 如何使手动重试线程安全

Java 如何使手动重试线程安全,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我正在尝试手动重试。但是我觉得代码不是线程安全的。 任何人都可以提供建议,如何使其线程安全 while (retryCounter < maxRetries) { try { //TODO - add delay with config Thread.sleep(3000); t.run(); break; } catch (Exception e) {

我正在尝试手动重试。但是我觉得代码不是线程安全的。 任何人都可以提供建议,如何使其线程安全

while (retryCounter < maxRetries) {
          try {
            //TODO - add delay with config
            Thread.sleep(3000);
            t.run();
            break;
          } catch (Exception e) {
            retryCounter++;
            //TODO - Add audit logs
            if (retryCounter >= maxRetries) {
              LOG.info("Max retries exceeded");
              //TODO - remove exception add audit logs
              throw new RuntimeException("Max retry exceeded");
            }
          }
        }
while(retryCounter=maxRetries){
LOG.info(“超过最大重试次数”);
//TODO-删除异常添加审核日志
抛出新的RuntimeException(“超出最大重试次数”);
}
}
}

提前感谢

正如@SteffenJacobs所指出的,
t.run
不会在单独的线程上执行运行逻辑,而是在进行调用的线程上执行。如果将
t.run
替换为
t.start
,则运行逻辑将在不同的线程上异步执行,这意味着新线程中的异常将永远不会由
catch
块处理。例如,下面的代码:

public static void main(String[] args) {
    int retryCounter = 0;
    int maxRetries = 3;

    Thread t = new Thread(new Runnable() {
        public void run() {
            System.out.println("..." + Thread.currentThread());
            throw new RuntimeException("Thrown by me!!!");
        }});

    while (retryCounter < maxRetries) {
        try {
            Thread.sleep(3000);
            System.out.println("***" + Thread.currentThread());
            t.start();
            break;
        } catch (Exception e) {
            System.out.println("retrying attempt " + retryCounter);
            System.out.println(e);
            retryCounter++;
            if (retryCounter >= maxRetries) {
                throw new RuntimeException("Max retry exceeded");
            }
        } finally {
            System.out.println("in finally");
        }
    }
}
底线要检测线程任务中的错误,您需要考虑一种不同的方法。
可以考虑使用<代码>未来< /Calp> s()。在这种情况下,当启动任务的代码等待未来时,您的任务将需要返回其执行状态。获取检查状态并根据需要重新运行任务

大卫·索罗科的答案非常接近,但我认为它不需要修改。由于您的代码将在
多线程
环境下运行,因此我们应该注意同步

如果在循环时多个线程试图进入
,则可能会启动两次调用
重试线程
,其中两次调用
t.start()
。理想情况下,我们应该在while循环的单个迭代中只启动单个调用

小改动:

在类级别中声明
LOCK
对象

// Object to ensure thread safety between multiple threads
private final LOCK = new Object();
使用
锁定
对象和
同步

synchronized(LOCK) { // This will ensure single thread entry at a time
    while (retryCounter < maxRetries) {
        try {
            Thread.sleep(3000);
            System.out.println("***" + Thread.currentThread());
            t.start();
            break;
        } catch (Exception e) {
            System.out.println("retrying attempt " + retryCounter);
            System.out.println(e);
            retryCounter++;
            if (retryCounter >= maxRetries) {
                throw new RuntimeException("Max retry exceeded");
            }
        } finally {
            System.out.println("in finally");
        }
    }
}

您知道
t.run()
会同步调用
t
对象的run方法,并且实际上不会启动异步线程?为什么您觉得它不是线程安全的?甚至没有“线”。代码在单线程中运行。我的应用程序将在服务器上运行,但不会在服务器上运行。它的类型为
t
not
thread
?不,它是一种接口方法如果没有处理异常,为什么代码打印RuntimeException它不是由您/我的代码打印的,它是由VM的异常处理程序打印的。我无法理解为什么运行时异常是通过我修改了示例代码来强调异常的来源
synchronized(LOCK) { // This will ensure single thread entry at a time
    while (retryCounter < maxRetries) {
        try {
            Thread.sleep(3000);
            System.out.println("***" + Thread.currentThread());
            t.start();
            break;
        } catch (Exception e) {
            System.out.println("retrying attempt " + retryCounter);
            System.out.println(e);
            retryCounter++;
            if (retryCounter >= maxRetries) {
                throw new RuntimeException("Max retry exceeded");
            }
        } finally {
            System.out.println("in finally");
        }
    }
}
final AtomicInteger retryCounter = new AtomicInteger(0);
final AtomicInteger maxRetries = new AtomicInteger(3);