简体   繁体   中英

Filter ExecutorService ThreadPool prior to running pending tasks

Let's say I have an ExecutorService (.newFixedThreadPool(2)) that takes a series of requests. For the sake of simplicity, they are just: { String url }

Let's say I have urls [ aaa, bbb, ccc, aaa, ddd, aaa, ... ] in that order. (Yes, aaa is repeated multiple times)

Those url events come in asynchronously, and so are each submitted to the ExecutorService as they arrive.

Is there a way to have the ExecutorService check a condition before allowing the next pending item to run? Eg check if the future pending results contains 'aaa' and, if so, discard it so only the most recent is triggered.

I've come up with a hacky way by mapping the url requests to a timestamp and having the threads die if their timestamps no longer match. But, this has the consequence of the ExecutorService still running all requests leading up to the latest, which can be pretty heavy if many are submitted consecutively.

Any suggestions would be greatly appreciated... Thanks!

Just some brainstorming which I hope will help you:

What about maintaining a "url event queue" as events come in, and then have a type of "queue processor thread" that manages the "url event queue" and kick off ExecutorService threads with the correct "url event" as required?

So if I followed you correctly, your solution is
1) event comes in
2) kick off a thread

My suggestion
1) event comes in, put it in a queue
2) "queue processor thread" sees there's something in the queue, does some queue cleanup etcetera as necessary and passes the next "url event" to the ExecutorService.

You said:

I've come up with a hacky way by mapping the url requests to a timestamp and having the threads die if their timestamps no longer match. But, this has the consequence of the ExecutorService still running all requests leading up to the latest, which can be pretty heavy if many are submitted consecutively.

Hmmm, interesting. Remember, creating threads are expensive. How are you instantiating your ExecutorService - because it shouldn't be necessary to create new threads. Maybe you were just saying that the ExecutorService overhead and looking at all the events within each thread were expensive, but let me just say this in any case:

Eg:

int threadPoolSize = Runtime.getRuntime().availableProcessors();
ExecutorService threadPool = Executors.newFixedThreadPool(threadPoolSize);

Just the Javadoc for that method out of interest:

/**
 * Creates a thread pool that reuses a fixed number of threads
 * operating off a shared unbounded queue.  At any point, at most
 * {@code nThreads} threads will be active processing tasks.
 * If additional tasks are submitted when all threads are active,
 * they will wait in the queue until a thread is available.
 * If any thread terminates due to a failure during execution
 * prior to shutdown, a new one will take its place if needed to
 * execute subsequent tasks.  The threads in the pool will exist
 * until it is explicitly {@link ExecutorService#shutdown shutdown}.
 *
 * @param nThreads the number of threads in the pool
 * @return the newly created thread pool
 * @throws IllegalArgumentException if {@code nThreads <= 0}
 */
public static ExecutorService newFixedThreadPool(int nThreads) {

I like the queue model :) Remember, now we will just have one thread that looks at the "url event queue". It sounds like in your example each thread inside the ExecutorService unfortunately has to look at the queue and figure out if it needs to process its "url event".

Hope this helps...

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