Java 进程的 HealthChecker

HealthChecker for Java Process

我想创建一个健康检查程序,它将检查 java 进程的健康状况。我的进程做了很多事情并且是多线程的。可能会抛出各种异常,例如 Service / SQL / IO 等。我的计划是调用 HealthChecker 来检查各个线程中来自 catch 块的进程。这将检查所有不同的健康状况,如果有任何问题,它将暂停线程,并适当记录。将有其他进程读取该进程的日志,并提醒支持人员采取适当的措施。

下面是 java 过程的一般结构。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Schedular {
    private static int numOfTasks = 10 ;

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(5);
        while(true){
            for(int i=0;i<numOfTasks;i++){
                service.execute(new Workers());
            }
        }
    }
}

class Workers implements Runnable{
    @Override
    public void run() {
        /*
         * This can throw different exceptions , eg:    
         */
        try{

        }catch(Exception e){
            e.printStackTrace();
            HealthChecker.checkHealth();
        }
    }
}

class HealthChecker{
    public static void checkHealth() {
        //Check health and then , log and pause all the threads 

    }
}

我想不出暂停所有线程的方法。如果出现数据库异常,我希望所有线程都暂停。我正在请求一些建议。

您与最佳实践相去甚远,但您没有询问监控线程健康状况的最佳实践 - 所以我不会回答这个问题。相反,我只会回答您提出的问题:如何暂停由 ExecutorService 管理的一组线程?

假设你的 Workers.run() 最终会在没有干预的情况下结束(换句话说,它不是无限循环——有意或无意),正确的做法是调用 service.shutdown()(其中服务是您的 ExecutorService 实例)。为此,您可以将服务作为新参数传递给 HealthCheck.healthCheck()。调用 shutdown() 将允许当前-运行 个线程完成,然后停止执行程序。

如果 Workers.run() 不会自然完成,最佳做法是您需要更改代码以使其完成。您可以调用 Thread.stop() 方法来暂停线程,还可以调用 Thread.suspend() 方法来暂停线程。这两个都是你使用的双重坏主意,原因有两个:

  1. 它们已被弃用,将使线程处于极不健康的状态。你用了以后会遇到很棘手的问题。
  2. 您正在使用 ExecutorService。这意味着您将线程管理委托给 class。如果你去搞乱 ExecutorService 下的 Threads 的状态,它就不能为你管理线程池,同样,你以后会遇到非常困难的问题。

您需要一种方法来阻止线程,直到发生某些允许线程继续运行的事件。我发现代码存在一些主要问题:

1) 主线程中的 while(true) 可能会导致 WhosebugError。随着 while 循环的每次迭代,您将向执行程序添加 10 个以上的线程,并且这将无限继续。

2) 你的 运行() 中没有循环,所以即使捕获到异常并且我们等待 HealthCheck,运行() 方法仍然会退出。如果您可以不断地从主线程执行新线程来代替已终止的线程,则 运行() 中不需要循环,但主循环中目前不存在该逻辑。

但是,将这些问题搁置一旁是阻塞工作线程直到发生某些事件(可能是 HealthCheck 全部清除)的一种方法。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Schedular {
    private static int numOfTasks = 10 ;

    public static void main(String[] args) {
        ExecutorService service = Executors.newFixedThreadPool(5);
        HealtchChecker hChecker = new HealthChecker();
        for(int i=0;i<numOfTasks;i++){
            service.execute(new Workers(hChecker));
        }
    }
}

class Workers implements Runnable{

    private HealtchChecker hChecker;

    public Workers(HealtchChecker hChecker){
        this.hChecker = hChecker;
    }

    @Override
    public void run() {
        /*
         * This can throw different exceptions , eg:    
         */
         while(true) {
            try{

            }catch (InterruptedException ie) {
                throw ie;   
            }catch(Exception e){
                e.printStackTrace();
                HealthChecker.checkHealth();
            }
         }
    }
}

class HealthChecker implements Runnable {

    private final Semaphore semaphore = new Semaphore(1, true);

    public void checkHealth() {
        try {
            semaphore.acquire();
        } finally {
            semaphore.release();
        }
    }

    @Override
    public void run(){
        //code to check for errors that cause threads to pause.
        if (inErrorState) {
            semaphore.acquire();
        } else {
            semaphore.release();
        }
    }

}

有几件事值得一提。

1) 主线程只创建 10 个线程,数量没有限制。您可以根据需要进行调整。

2) Worker 线程是长期存在的,这意味着它会继续 运行ning 即使它遇到异常,除了 InterruptException。

3) HealthCheck不再是静态对象。它是一个共享对象。

4) HealthCheck 是一个 运行nable,可以在其自己的线程中执行以监视错误。我没有添加代码来执行这个线程。

5) HealCheck 使用信号量使线程阻塞,直到错误状态被清除。我寻找可以执行此操作的其他对象,例如 CountDownLatch 或 CyclicBarrier 或 Phaser,但这个对象最接近于为我们提供从一个点阻塞所有线程所需的东西(运行() 方法)。

它并不完美,但我认为它能让你更接近你想要的东西。