Java 提交新任务时取消当前任务的ExecutorService

Java 提交新任务时取消当前任务的ExecutorService,java,executorservice,Java,Executorservice,考虑一个用户界面,它接受需要很长时间初始化的服务的配置设置(例如,JDBC连接的参数)。我们希望我们的用户界面在服务初始化时保持响应。如果用户进行了其他更改,则应取消初始化并使用新参数重新启动 由于在用户键入每个字符时,参数会合并到配置中,因此有可能在一行中创建多个初始化请求。只应执行最后一个 我们编写了一些代码来实现这一结果,但似乎这种行为非常适合作为ExecutorService实现。在我们将一切重构为ExecutorService之前,我想我会问,世界上是否已经有类似的实现 更具体地说:

考虑一个用户界面,它接受需要很长时间初始化的服务的配置设置(例如,JDBC连接的参数)。我们希望我们的用户界面在服务初始化时保持响应。如果用户进行了其他更改,则应取消初始化并使用新参数重新启动

由于在用户键入每个字符时,参数会合并到配置中,因此有可能在一行中创建多个初始化请求。只应执行最后一个

我们编写了一些代码来实现这一结果,但似乎这种行为非常适合作为ExecutorService实现。在我们将一切重构为ExecutorService之前,我想我会问,世界上是否已经有类似的实现

更具体地说:

Executor服务将有一个工作线程。提交新任务后,当前任务即被取消(工作人员中断)。然后捕获新任务以供下一次执行。如果提交了另一个任务,则会再次取消当前任务,并将“下一次执行”任务设置为此新任务。当工作线程最终选择执行下一个任务时,它将始终是提交的最后一个任务-所有其他任务都将被取消或丢弃


有人愿意分享这样的实现吗?或者是否有一个标准的库来涵盖这种行为?这并不难实现,但要确定线程安全性可能会很棘手,因此如果可以的话,我宁愿使用经过验证的代码。

您可能需要在执行器中添加一个丢弃策略

您将获得
0已提交
1提交
2提交
3提交
4提交
5提交
6提交
7提交
8提交
9提交
9完成
公共静态void main(字符串[]args)引发SecurityException,
NoSuchMethodException{
最后一个方法interruptWorkers=ThreadPoolExecutor.class
.getDeclaredMethod(“中断工作人员”);
interruptWorkers.setAccessible(true);
ExecutorService executor=新线程池executor(1,1,0L,
TimeUnit.ms,新的SynchronousQueue(),
新的RejectedExecutionHandler(){
@凌驾
公共无效拒绝执行(可运行r,
线程池执行器(执行器){
如果(!executor.isShutdown()){
试一试{
中断工人。调用(执行者);
执行人。执行人(r);
}捕获(IllegalArgumentException e){
e、 printStackTrace();
}捕获(非法访问例外e){
e、 printStackTrace();
}捕获(调用TargetException e){
e、 printStackTrace();
}
}
}
});

对于(int i=0;i我最终得出了以下结论-我对任何评论都感兴趣:

public class InterruptingExecutorService extends ThreadPoolExecutor{
    private volatile FutureTask<?> currentFuture;

    public InterruptingExecutorService(boolean daemon) {
        super(0, 1, 1000L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), 
                daemon ? new DaemonThreadFactory() : Executors.defaultThreadFactory());

    }

    public static class DaemonThreadFactory implements ThreadFactory{
        ThreadFactory delegate = Executors.defaultThreadFactory();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = delegate.newThread(r);
            t.setDaemon(true);
            return t;
        }

    }

    private void cancelCurrentFuture(){
        // cancel all pending tasks
        Iterator<Runnable> it = getQueue().iterator();
        while(it.hasNext()){
            FutureTask<?> task = (FutureTask<?>)it.next();
            task.cancel(true);
            it.remove();
        }

        // cancel the current task
        FutureTask<?> currentFuture = this.currentFuture;
        if(currentFuture != null){
            currentFuture.cancel(true);
        }
    }

    @Override
    public void execute(Runnable command) {
        if (command == null) throw new NullPointerException();

        cancelCurrentFuture();
        if (!(command instanceof FutureTask)){ // we have to be able to cancel a task, so we have to wrap any non Future
            command = newTaskFor(command, null);
        }
        super.execute(command);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        // it is safe to access currentFuture like this b/c we have limited the # of worker threads to only 1
        // it isn't possible for currentFuture to be set by any other thread than the one calling this method
        this.currentFuture = (FutureTask<?>)r;
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        // it is safe to access currentFuture like this b/c we have limited the # of worker threads to only 1
        // it isn't possible for currentFuture to be set by any other thread than the one calling this method
        this.currentFuture = null;
    }
}
公共类中断执行器服务扩展ThreadPoolExecutor{
私人不稳定的未来;
公共中断执行器服务(布尔守护进程){
超级(0,1100L,TimeUnit.ms,
新建LinkedBlockingQueue(),
守护进程?新的DaemonThreadFactory():Executors.defaultThreadFactory());
}
公共静态类DaemonThreadFactory实现ThreadFactory{
ThreadFactory委托=Executors.defaultThreadFactory();
@凌驾
公共线程newThread(可运行的r){
线程t=委托.newThread(r);
t、 setDaemon(true);
返回t;
}
}
私有void cancelCurrentFuture(){
//取消所有挂起的任务
迭代器it=getQueue().Iterator();
while(it.hasNext()){
FutureTask=(FutureTask)it.next();
任务。取消(true);
it.remove();
}
//取消当前任务
FutureTask currentFuture=this.currentFuture;
if(currentFuture!=null){
currentFuture.cancel(true);
}
}
@凌驾
public void execute(Runnable命令){
如果(command==null)抛出新的NullPointerException();
取消当前未来();
如果(!(FutureTask的命令instanceof)){//我们必须能够取消一项任务,因此我们必须包装任何非未来任务
command=newTaskFor(command,null);
}
super.execute(命令);
}
@凌驾
执行前受保护的void(线程t,可运行r){
//像这样访问currentFuture是安全的b/c我们已将工作线程的#限制为仅1个
//currentFuture不可能由调用此方法的线程以外的任何其他线程设置
this.currentFuture=(FutureTask)r;
}
@凌驾
执行后受保护的无效(可运行的r、可丢弃的t){
//像这样访问currentFuture是安全的b/c我们已将工作线程的#限制为仅1个
//currentFuture不可能由调用此方法的线程以外的任何其他线程设置
this.currentFuture=null;
}
}

ah-非常优雅…必须使用interruptWorkers方法有点令人不安,但这似乎确实是最好的方法。好的-interruptWorkers不是我正在运行的JDK的一部分(Oracle,1.6.034),所以这不起作用。关于使用公共API的方法的其他想法?我使用openjdk 1.6.024,并从sourceprivate void interruptWorkers()获得它。{final ReentrantLock mainLock=this.mainLock;mainLock.lock();try{for(Worker w:workers){
public class InterruptingExecutorService extends ThreadPoolExecutor{
    private volatile FutureTask<?> currentFuture;

    public InterruptingExecutorService(boolean daemon) {
        super(0, 1, 1000L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(), 
                daemon ? new DaemonThreadFactory() : Executors.defaultThreadFactory());

    }

    public static class DaemonThreadFactory implements ThreadFactory{
        ThreadFactory delegate = Executors.defaultThreadFactory();

        @Override
        public Thread newThread(Runnable r) {
            Thread t = delegate.newThread(r);
            t.setDaemon(true);
            return t;
        }

    }

    private void cancelCurrentFuture(){
        // cancel all pending tasks
        Iterator<Runnable> it = getQueue().iterator();
        while(it.hasNext()){
            FutureTask<?> task = (FutureTask<?>)it.next();
            task.cancel(true);
            it.remove();
        }

        // cancel the current task
        FutureTask<?> currentFuture = this.currentFuture;
        if(currentFuture != null){
            currentFuture.cancel(true);
        }
    }

    @Override
    public void execute(Runnable command) {
        if (command == null) throw new NullPointerException();

        cancelCurrentFuture();
        if (!(command instanceof FutureTask)){ // we have to be able to cancel a task, so we have to wrap any non Future
            command = newTaskFor(command, null);
        }
        super.execute(command);
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        // it is safe to access currentFuture like this b/c we have limited the # of worker threads to only 1
        // it isn't possible for currentFuture to be set by any other thread than the one calling this method
        this.currentFuture = (FutureTask<?>)r;
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        // it is safe to access currentFuture like this b/c we have limited the # of worker threads to only 1
        // it isn't possible for currentFuture to be set by any other thread than the one calling this method
        this.currentFuture = null;
    }
}