简体   繁体   English

从正在运行的任务中关闭ExecutorService

[英]Shutting down an ExecutorService from running task

I'm using a single threaded ScheduledExecutorService in order to process some Runnable tasks. 我正在使用单线程ScheduledExecutorService来处理一些Runnable任务。 When my Runnable has finished its work, it reschedules itself in the ScheduledExecutorService with a variable delay. 当我的Runnable完成其工作时,它会在ScheduledExecutorService重新安排自己的变量延迟。 This happens indefinitely until the Runnable catches an Exception . 这种情况无限期地发生,直到Runnable捕获Exception

public class Runner { 

    ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

    public void startWorking() { 
        // Single-shot start
        service.submit(new Task(service));
    }

    public void stopWorking() { 
        service.shutDown();
        // Do some other stuff
    }

    private static final class Task implements Runnable { 
        ScheduledExecutorService service;
        private Task(ScheduledExecutorService service) {
            this.service = service;
        }
        @Override 
        public void run() { 
            try { 
                // Do some work...
                service.schedule(this, variableDelay, TimeUnit.SECONDS);
            }
            catch(SomethingHappenedException e){ 
                // Shutdown service
            }
        }
    }   
}

Can I shutdown() or shutdownNow() the ExecutorService safely from Task.run() ? 我可以从Task.run()安全地shutdown()shutdownNow() ExecutorService吗? Something doesn't look right if the thread will be provoking an interrupt to itself. 如果线程会激发对自身的中断,那么看起来不对。

When an exception is caught while executing Task , I'd like to shutdown the service , ideally calling Runner.stopWorking() . 当执行Task捕获到异常时,我想shutdownservice ,理想情况下调用Runner.stopWorking()

I know I could use a Callable instead and let Runner manage reschedulings, but I'd like to keep this structure ( Runner will have more analogous service s, so an infinite loop just doesn't look right there). 我知道我可以使用Callable而让Runner管理重新安排,但我想保留这个结构( Runner将有更多类似的service ,所以无限循环只是看起来不正确)。

I guess I could subclass ScheduledThreadPoolExecutor to override afterExecute and handle shutdown there, using a reference to Runner . 我想我可以afterExecute ScheduledThreadPoolExecutor以使用对Runner的引用来覆盖afterExecute并在那里处理shutdown。

public class Runner { 
    ScheduledExecutorService service = new ScheduledThreadPoolExecutor(1){
      protected void afterExecute(Runnable r, Throwable t) { 
        if (t != null) { 
            Runner.this.stopWorking();
        }
    };
    // ...
}

My concern with this approach is, if afterExecute will be invoked by the thread that ran the Task , this would have the same effects as calling shutDown() from Task.run() itself. 我对这种方法的关注是,如果运行Task的线程调用afterExecute ,这将与从Task.run()本身调用shutDown()具有相同的效果。

Is there any other alternative approach to this? 还有其他替代方法吗?

Can I shutdown() or shutdownNow() the ExecutorService safely from Task.run()? 我可以从Task.run()安全地关闭()或shutdownNow()ExecutorService吗? Something doesn't look right if the thread will be provoking an interrupt to itself. 如果线程会激发对自身的中断,那么看起来不对。

shutdown() will not interrupt already running tasks but will prevent new task from beeing submited. shutdown()不会中断已经运行的任务,但会阻止新任务被提交。 shutdownNow() doesn't interrupt running tasks either, but "signals" all workers that they should be terminated. shutdownNow()也不会中断正在运行的任务,但会“通知”所有工作人员应该终止它们。 It is up to Thread implementation (or rather Runnable itself) will it honor such signal ( Thread.isTerminated() as I remember) or not. 它取决于Thread实现(或者更确切地说是Runnable本身)它是否会尊重这样的信号(我记得的Thread.isTerminated() )。

And yes, it is perfectly fine for thread to signal itself to be terminated. 是的,线程发出信号终止是完全没问题的。 So it is safe to shutdown() executor from running task. 因此, shutdown()执行器从运行任务中是安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM