简体   繁体   中英

ThreadPool reject tasks when queue is full using RejectedExecutionHandler

I know that are lots of questions on this subject but I'm not sure that I found the correct way of doing this.

What I want: having a ThreadPoolExecutor with a constant number of threads, submit tasks to it. When the internal queue of the ThreadPoolExecutor is full, use a custom RejectedExecutionHandler to reject the last(or first) task submitted to thread pool executor which is in queue(in my example is the last one). I've made some tests and a simple example, but still not sure if this is the right way to do it:

 import java.util.concurrent.*;

class TestThread implements Runnable {
    public int id;

    public TestThread(int i) {
        id = i;
    }

    @Override
    public void run() {
        try {
            Thread.sleep(20_000);
            System.out.println(" finished task " + id);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }
}

public class Application {
    public static void main(String[] args) {
        LinkedBlockingDeque<Runnable> blockingQueue = new LinkedBlockingDeque<>(10);

        ThreadPoolExecutor executor = new ThreadPoolExecutor(2,
                2,
                10L,
                TimeUnit.MINUTES,
                blockingQueue,
                (r, executor1) -> {
                    TestThread r1 = (TestThread) blockingQueue.removeLast();
                    System.out.println("removed " + r1.id);
                });
        executor.prestartAllCoreThreads();


        int i = 0;
        while (i <= 15) {
            TestThread testThread = new TestThread(i);
            System.out.println("submit task " + i);
            executor.execute(testThread);
            System.out.println("queue size " + blockingQueue.stream().count());
            i++;
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        i = 0;
        while (i <= 5) {
            TestThread testThread1 = new TestThread(i);
            System.out.println("submit task " + i);
            executor.execute(testThread1);
            System.out.println("queue size " + blockingQueue.stream().count());
            i++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        try {
            executor.shutdown();
            executor.awaitTermination(10L, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            executor.shutdownNow();
            e.printStackTrace();
        }
    }
}

Do I miss something here?

LE: do I need to lock the queue when removing the element from it?

You don't want to do this:

System.out.println("queue size " + blockingQueue.stream().count());

The Stream.count() method is a terminal operation. It will stream all of your queue items off your queue while counting them, so the queue will end up being empty even if your println reports it as not empty. Use blockingQueue.size() instead.

You should not lock the queue when removing an element from it. BlockingQueues are designed to be used from multiple threads concurrently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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