Original: http://stackoverflow.com/questions/4521983/ java-executorservice-that-blocks-on-submission-after-a-certain-queue-size/4522411#4522411
Problem:
Need to solve only one IO read and write producer's task parallelization, each consumer data in memory, want to control the number of consumers waiting. Threadpoolexecutor class with Java
Workaround 1: Implement a queue, and the Offer method is also blocked
Disadvantage: Changed the original intention of the Threadpoolexecutor, because the task is to block the way, then reach the maximumpoolsize after the thread, because the method of the offer is blocked, can not take the idle thread back
public class Limitedqueue < E > extends Linkedblockingqueue < e > {public limitedqueue (int maxSize) {super ( MaxSize); @Override public Boolean offer (e e) {//Turn offer () and add () to a blocking calls (unless interrupted) try {put (e); return true; catch (Interruptedexception IE) {thread.currentthread (). interrupt ();} return false; } }
Workaround 2: Use Rejectedexecutionhandler, Method 1
The code for Threadpoolexecutor.execute (Runnable) is as follows
if (IsRunning (c) && workqueue.offer (command)) {int recheck = ctl. get (); if (! isrunning (recheck) && re Move (command)) reject (command); else if (workercountof (recheck) = = 0) Addworker (null, FALSE); else if (! Addworker (command, False)) reject (command);
An offer block causes else if (!addworker (command, False)) to be inaccessible, using the Rejectedexecutionhandler
public void Rejectedexecution (Runnable R, Threadpoolexecutor executor) {try {if (! Executor.isshutdown ()) {executor.ge Tqueue (). put (R); } catch (Interruptedexception e) {thread.currentthread (). interrupt (); throw new Rejectedexecutionexception ("Executor is interrupted while the task is waiting to put on work queue, E);}
Description: Corepoolsize==0 can lead to problems, put methods lead to inconsistent threadpoolexecutor packaging, and have an impact, corepoolsize < maxpoolsize is usually useful in this way.
Workaround 3: Subclass Threadpoolexecutor, before and after submission, using semaphores to limit
public class Boundedexecutor extends threadpoolexecutor{private final semaphore semaphore, public boundedexecutor (int bo und) {Super (bound, Integer.max_value, 60L, Timeunit.seconds, new Synchronousqueue < Runnable > ()); semaphore = NE W Semaphore (bound); }/* *submits task to execution pool, but blocks while number of running threads * has reached the bound limit/public & Lt T > Future < T > submitbutblockiffull (Final callable < T > Task) throws interruptedexception{Semaphore.acq Uire (); return submit (Task); @Override protected void AfterExecute (Runnable R, Throwable t) {Super.afterexecute (r, T); Semaphore.release ();}
Method 4: Use the lock and condition variable in Threadpoolexecutor's Beforeexecute/afterexecute fuss
Import Java.util.concurrent.BlockingQueue; Import Java.util.concurrent.ThreadPoolExecutor; Import Java.util.concurrent.TimeUnit; Import java.util.concurrent.locks.Condition; Import Java.util.concurrent.locks.ReentrantLock; * * * Blocks Current task execution if there isn't enough resources for it. * Maximum Task Count usage controlled by Maxtaskcount. * * public class Blockingthreadpoolexecutor extends Threadpoolexecutor {private final Reentrantlock Tasklock = new Reentra NTLock (); Private final Condition unpaused = Tasklock.newcondition (); private final int maxtaskcount; private volatile int currenttaskcount; Public blockingthreadpoolexecutor (int corepoolsize, int maximumpoolsize, long keepalivetime, Timeunit unit, Blockingqueue < Runnable > workqueue, int maxtaskcount) {super (corepoolsize, Maximumpoolsize, KeepAliveTime, Unit, Workqueue); this. Maxtaskcount = Maxtaskcount; }/* * Executes task if there is enough system resources for it. otherwise * waits. * * @OveRride protected void BeforeExecute (Thread T, Runnable R) {Super.beforeexecute (T, r); Tasklock. Lock (); try {//Spin WHI Le we won't have enough capacity for this job while (Maxtaskcount < Currenttaskcount) {try {unpaused.await ();} CA TCH (interruptedexception e) {t.interrupt ();}} Currenttaskcount + +; finally {Tasklock.unlock ();}} * * * Signalling that one more task is welcome */@Override protected void AfterExecute (Runnable R, Throwable t) {super. AfterExecute (r, T); Tasklock. Lock (); try {currenttaskcount-; Unpaused.signalall ();} finally {Tasklock.unlock ()}} }
Workaround 5: This method is not universal, set to a blocking queue with fixed length future, consumer consumption blocking the future in the queue, the producer submits the task by put to the blocking queue for processing
Final Executorservice executor = Executors.newfixedthreadpool (numworkerthreads); Final Linkedblockingqueue < Future > futures = new linkedblockingqueue <> (maxqueuesize); try {thread taskgenerator = new Thread () {@Override public void run () {while (Reader.hasnext) {Callable task = Generat ETask (Reader.next ()); Future Future = executor.submit (Task); try {//If queue is full blocks until a task/are completed and hence no future tasks are submitted. Futures.put (Compoun Dfuture); The catch (Interruptedexception ex) {Thread.CurrentThread (). interrupt ();}} Executor.shutdown (); } taskgenerator.start (); Read from queue as long as task are being generated//while queue has elements in it (taskgenerator.isalive) || ! Futures.isempty ()) {Future compoundfuture = Futures.take ();//Do Something} catch (Interruptedexception ex) {Thread. CurrentThread (). interrupt (); The catch (Executionexception ex) {throw new MyException (ex);} finally {Executor.shutdownnow ();}
other documents available for reference http://howtodoinjava.com/core-java/multi-threading/ how-to-use-blockingqueue-and-threadpoolexecutor-in-java/
Http://stackoverflow.com/questions/7556465/why-threadpoolexecutor-has-blockingqueue-as-its-argument
Http://stackoverflow.com/questions/3446011/threadpoolexecutor-block-when-queue-is-full
http://stackoverflow.com/questions/2001086/ how-to-make-threadpoolexecutors-submit-method-block-if-it-is-saturated/2001205#2001205
http://stackoverflow.com/questions/2001086/how-to-make-threadpoolexecutors-submit-method-block-if-it-is-saturated