线程关闭时如何通知?

时间:2014-09-15 19:08:02

标签: java multithreading

在java中,我有ExecutorService,它运行时为true,而Throwable捕获clouse。我发现线程不时会下降。这意味着系统停止功能。 所以我的问题是,首先,我怎样才能抓住“线程杀死”事件(为了在这种情况下向我发送电子邮件)? 此外,这个线程如何发生故障?

代码是:

ExecutorService changesTrackerThread = Executors.newSingleThreadExecutor();
changesTrackerThread.submit(queueUpdater());        

private Runnable queueUpdater() {
    return new Runnable() {
        @Override
        public void run() {
            while (true)
            {
                try
                {                                       
                    // do some code, then sleep
                    Thread.sleep(2000L);
                } catch (Throwable t)
                {
                    _log.error("something bad happened, but the loop should keep running", t);
                }
            }

        }
    };

2 个答案:

答案 0 :(得分:3)

首先,为什么你在这里使用while循环??

您应该使用scheduled executor

ExecutorService changesTrackerThread = Executors.newSingleThreadScheduledExecutor()();
changesTrackerThread.scheduleAtFixedRate(new queueUpdater(), 0, 2, TimeUnit.SECONDS);        

private Runnable queueUpdater() {
    return new Runnable() {
        @Override
        public void run() {
                try
                {                                       
                    // do some code

                } catch (Throwable t)
                {
                    _log.error("something bad happened", t);
                }

        }
    };

我不知道为什么你的线程会死掉,请告诉我们完整的代码。

但是这样,即使线程死亡,Excecutor也会在给定的时间段后重新运行它(在本例中为2秒。

答案 1 :(得分:1)

正如其他人所说,您可以将while (true)sleep()循环替换为ScheduledExecutorService。在此类服务上安排重复任务将返回ScheduledFuture,您可以使用该ScheduledExecutorService svc = Executors.newScheduledThreadPool(1); 检查此任务的状态,或者在需要时取消它。这将使您能够从代码中删除try / catch块。

像这样启动服务:

newScheduledThreadPool()

我会使用newSingleThreadScheduledExecutor()而不是void doSomeCode() { // do some code } ScheduledFuture<?> sf = svc.scheduleAtFixedRate(this::doSomeCode, 0L, 2L, TimeUnit.SECONDS); ,因为前者会在必要时重新启动线程。

然后,安排这样的工作:

doSomeCode()

(或者,如果您希望可以将ScheduledFuture内联为lambda或匿名内部类。)

如果任务因异常而失败,会发生什么?返回的sf.get()对象允许您以各种方式检查状态。如果你有一个可以专门用于等待失败的线程,你可以让它调用ExecutionException,它会抛出一个ScheduledFuture.get()来包装导致任务失败的异常。否则,它会无限期地阻止。 Future.get()有点奇怪,与普通的sf.get()调用不同,它永远不会返回值;它总是抛出异常。

当/如果任务失败,sf.isDone()的调用者可以记录异常并重新提交任务,或者其他任何事情。如果您不想无限期地阻止某个主题,则可以使用sf.get(0L, TimeUnit.SECONDS)sf.get()轮询失败。请注意,Throwable的两个重载都通过抛出异常的类型传达其返回信息的全部,这可能会使它们使用起来有些不方便。

可以在任务本身中放置异常处理,捕获ScheduledFuture并继续,无论如何,这可能会有效。它确实将日志记录/重新启动/重新提交策略烘焙到任务本身,这可能是令人不愉快的。使用{{1}}可以将这些策略与任务执行的实际工作分开。