3131import javax .annotation .concurrent .ThreadSafe ;
3232import java .util .List ;
3333import java .util .Objects ;
34- import java .util .concurrent .ConcurrentHashMap ;
35- import java .util .concurrent .ConcurrentMap ;
36- import java .util .concurrent .ExecutorService ;
37- import java .util .concurrent .Executors ;
34+ import java .util .concurrent .*;
3835
3936import static java .lang .Math .floorMod ;
4037
@@ -67,16 +64,16 @@ private ConseqServiceFactory(int concurrency) {
6764 /**
6865 * @return ExecutorService factory with default concurrency
6966 */
70- public static ConseqServiceFactory instance () {
71- return new ConseqServiceFactory (Runtime .getRuntime ().availableProcessors ());
67+ public static @ Nonnull ConseqServiceFactory instance () {
68+ return instance (Runtime .getRuntime ().availableProcessors ());
7269 }
7370
7471 /**
7572 * @param concurrency
7673 * max number of tasks possible to be executed in parallel
7774 * @return ExecutorService factory with given concurrency
7875 */
79- public static ConseqServiceFactory instance (int concurrency ) {
76+ public static @ Nonnull ConseqServiceFactory instance (int concurrency ) {
8077 return new ConseqServiceFactory (concurrency );
8178 }
8279
@@ -86,12 +83,12 @@ public static ConseqServiceFactory instance(int concurrency) {
8683 @ Override
8784 public ExecutorService getExecutorService (@ NonNull Object sequenceKey ) {
8885 return this .sequentialExecutors .computeIfAbsent (bucketOf (sequenceKey ),
89- bucket -> new ShutdownDisabledExecutorService (Executors .newFixedThreadPool ( 1 )));
86+ bucket -> new ShutdownDisabledExecutorService (Executors .newSingleThreadExecutor ( )));
9087 }
9188
9289 @ Override
9390 public void close () {
94- sequentialExecutors .values ().forEach (ExecutorService :: close );
91+ sequentialExecutors .values ().forEach (ShutdownDisabledExecutorService :: closeDelegate );
9592 }
9693
9794 private int bucketOf (Object sequenceKey ) {
@@ -137,6 +134,32 @@ public void shutdown() {
137134 throw new UnsupportedOperationException (SHUTDOWN_UNSUPPORTED_MESSAGE );
138135 }
139136
137+ @ Override
138+ public void close () {
139+ throw new UnsupportedOperationException (SHUTDOWN_UNSUPPORTED_MESSAGE );
140+ }
141+
142+ void closeDelegate () {
143+ boolean terminated = isTerminated ();
144+ if (!terminated ) {
145+ shutdownDelegate ();
146+ boolean interrupted = false ;
147+ while (!terminated ) {
148+ try {
149+ terminated = awaitTermination (1L , TimeUnit .DAYS );
150+ } catch (InterruptedException e ) {
151+ if (!interrupted ) {
152+ shutdownDelegateNow ();
153+ interrupted = true ;
154+ }
155+ }
156+ }
157+ if (interrupted ) {
158+ Thread .currentThread ().interrupt ();
159+ }
160+ }
161+ }
162+
140163 void shutdownDelegate () {
141164 this .delegate .shutdown ();
142165 }
@@ -153,6 +176,8 @@ private interface ShutdownOperations {
153176 void shutdown ();
154177
155178 List <Runnable > shutdownNow ();
179+
180+ void close ();
156181 }
157182 }
158183}
0 commit comments