单线程处理任务而不排队进一步的请求

Mic*_*urd 9 java concurrency unit-of-work java.util.concurrent

我要求异步执行任务,同时丢弃任何进一步的请求,直到任务完成.

同步方法只是将任务排队,不会跳过.我最初想过使用SingleThreadExecutor,但也排队等待任务.然后我查看了ThreadPoolExecutor,但是它读取队列以获取要执行的任务,因此将执行一个任务并且至少有一个任务排队(其他任务可以使用ThreadPoolExecutor.DiscardPolicy丢弃).

我唯一能想到的就是使用信号量来阻止队列.我带着以下示例来展示我想要实现的目标.有更简单的方法吗?我错过了一些明显的事吗?

import java.util.concurrent.*;

public class ThreadPoolTester {
    private static ExecutorService executor = Executors.newSingleThreadExecutor();
    private static Semaphore processEntry = new Semaphore(1);

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 20; i++) {
            kickOffEntry(i);

            Thread.sleep(200);
        }

        executor.shutdown();
    }

    private static void kickOffEntry(final int index) {
        if (!processEntry.tryAcquire()) return;
        executor.
            submit(
                new Callable<Void>() {
                    public Void call() throws InterruptedException {
                        try {
                            System.out.println("start " + index);
                            Thread.sleep(1000); // pretend to do work
                            System.out.println("stop " + index);
                            return null;

                        } finally {
                            processEntry.release();
                        }
                    }
                }
            );
    }
}
Run Code Online (Sandbox Code Playgroud)

样本输出

start 0
stop 0
start 5
stop 5
start 10
stop 10
start 15
stop 15
Run Code Online (Sandbox Code Playgroud)

采取axtavt的答案并转换上面的例子给出了以下更简单的解决方案.

import java.util.concurrent.*;

public class SyncQueueTester {
    private static ExecutorService executor = new ThreadPoolExecutor(1, 1, 
            1000, TimeUnit.SECONDS, 
            new SynchronousQueue<Runnable>(),
            new ThreadPoolExecutor.DiscardPolicy());

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 20; i++) {
            kickOffEntry(i);

            Thread.sleep(200);
        }

        executor.shutdown();
    }

    private static void kickOffEntry(final int index) {
        executor.
            submit(
                new Callable<Void>() {
                    public Void call() throws InterruptedException {
                        System.out.println("start " + index);
                        Thread.sleep(1000); // pretend to do work
                        System.out.println("stop " + index);
                        return null;
                    }
                }
            );
    }
}
Run Code Online (Sandbox Code Playgroud)

axt*_*avt 11

看起来像SynchronousQueue所需策略支持的执行程序可以满足您的需求:

executor = new ThreadPoolExecutor(
    1, 1, 
    1000, TimeUnit.SECONDS, 
    new SynchronousQueue<Runnable>(),
    new ThreadPoolExecutor.DiscardPolicy());
Run Code Online (Sandbox Code Playgroud)