除了最后一个,如何停止池中的所有任务?

时间:2015-08-03 13:03:20

标签: java multithreading executorservice

我有一个单线程的固定池。当我提交新任务时,我想要停止除最后一个之外的所有旧线程。

private class MyPool extends ThreadPoolExecutor {

    public MyPool(long keepAliveTime, TimeUnit unit,
            BlockingQueue<Runnable> workQueue) {
        super(1, 1, keepAliveTime, unit, workQueue);
    }

    public boolean isReady() {
        return semaphore;
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        // Iterate all existed task and stop
        Future<T> future = super.submit(task);
        return future;
    }

    private volatile boolean semaphore;

}

运行任务代码:

private class MyTask implements Runnable {

    private volatile boolean isRun = true;
    private int id;

    public MyTask(int id) {
        this.id = id;
    }

    public void stop() {
        isRun = false;
    }

    @Override
    public void run() {
        try {
            System.out.println("Start " + id);
            if (isRun) {
                Thread.sleep(1000);
                System.out.println("Stop " + id);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }       
}

我创建了自己的类,但它没有正确工作,因为信号量对新任务也有影响。最好的方法是什么?

1 个答案:

答案 0 :(得分:1)

如果提交了新的Callable,则此ThreadPoolExecutor会终止正在运行的线程:

class MyPool extends ThreadPoolExecutor {
    private volatile Thread activeThread = null;
    private static final Field FutureTask$runner;

    static {
        try {
            FutureTask$runner = FutureTask.class.getDeclaredField("runner");
            FutureTask$runner.setAccessible(true);
        } catch (NoSuchFieldException e) {
            throw new Error(e);
        }
    }

    private static Thread getThread(FutureTask<?> task) {
        try {
            return (Thread) FutureTask$runner.get(task);
        } catch (IllegalAccessException e) {
            throw new Error(e);
        }
    }

    public MyPool() {
        super(1, 1,
            //whatever here
            5000, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>());
    }

    @Override
    public <T> Future<T> submit(Callable<T> task) {
        if(activeThread != null) {
            activeThread.stop(); //kill
        }
        FutureTask<T> activeTask = (FutureTask<T>)super.submit(task);
        activeThread = getThread(activeTask); //steal thread reference for killing
        return activeTask;
    }
}