You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/08/31 07:16:26 UTC

[isis] 01/03: ISIS-1974: (porting from 1.16.x) support sequential execution

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 539e004310ef7c2511e699ea01e00dca538304a8
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Aug 31 07:00:09 2018 +0200

    ISIS-1974: (porting from 1.16.x)  support sequential execution
    
    in ThreadPoolSupport
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1895
---
 .../core/runtime/threadpool/ThreadPoolSupport.java | 69 ++++++++++++++++++----
 1 file changed, 56 insertions(+), 13 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
index 5fb798e..7a37e70 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/threadpool/ThreadPoolSupport.java
@@ -19,6 +19,9 @@
 
 package org.apache.isis.core.runtime.threadpool;
 
+import static org.apache.isis.commons.internal.base._NullSafe.isEmpty;
+
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
@@ -28,12 +31,16 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+import javax.annotation.Nullable;
 
-import org.apache.isis.commons.internal.collections._Lists;
-import org.apache.isis.commons.internal.context._Context;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.commons.internal.context._Context;
+
 /**
  * ThreadPoolSupport is application-scoped, meaning ThreadPoolSupport is closed on
  * application's end of life-cycle.
@@ -48,6 +55,7 @@ public final class ThreadPoolSupport implements AutoCloseable {
 
     private final ThreadGroup group;
     private final ThreadPoolExecutor executor;
+    private final ThreadPoolExecutor sequentialExecutor;
 
     private ThreadPoolSupport() {
 
@@ -56,21 +64,26 @@ public final class ThreadPoolSupport implements AutoCloseable {
         final int corePoolSize = Runtime.getRuntime().availableProcessors();
         final int maximumPoolSize = Runtime.getRuntime().availableProcessors();
         final int keepAliveTimeSecs = 5;
+        
+        final ThreadFactory threadFactory = (Runnable r) -> new Thread(group, r);
 
         final int queueCapacity = 25;
-        final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(queueCapacity);
-
+        final Supplier<BlockingQueue<Runnable>> workQueueFactory = 
+                ()->new LinkedBlockingQueue<>(queueCapacity);
+        
+        
         executor = new ThreadPoolExecutor(
                 corePoolSize,
                 maximumPoolSize,
                 keepAliveTimeSecs, TimeUnit.SECONDS,
-                workQueue,
-                new ThreadFactory() {
-                    @Override
-                    public Thread newThread(final Runnable r) {
-                        return new Thread(group, r);
-                    }
-                });
+                workQueueFactory.get(),
+                threadFactory);
+        
+        sequentialExecutor = new ThreadPoolExecutor(1, 1, // fixed size = 1
+                keepAliveTimeSecs, TimeUnit.MILLISECONDS,
+                workQueueFactory.get(),
+                threadFactory);
+        
     }
 
     public static List<Object> join(final List<Future<Object>> futures) {
@@ -100,7 +113,16 @@ public final class ThreadPoolSupport implements AutoCloseable {
         return null;
     }
 
-    public List<Future<Object>> invokeAll(final List<Callable<Object>> callables) {
+    /**
+     * Executes specified {@code callables} on the default executor.  
+     * See {@link ThreadPoolExecutor#invokeAll(java.util.Collection)}
+     * @param callables nullable
+     * @return non-null
+     */
+    public List<Future<Object>> invokeAll(@Nullable final List<Callable<Object>> callables) {
+        if(isEmpty(callables)) {
+            return Collections.emptyList();
+        }
         try {
             return executor.invokeAll(callables);
         } catch (InterruptedException e) {
@@ -108,13 +130,34 @@ public final class ThreadPoolSupport implements AutoCloseable {
         }
     }
 
+    /**
+     * Executes specified {@code callables} on the sequential executor in sequence, one by one.
+     * @param callables nullable
+     * @return non-null
+     */
+    public List<Future<Object>> invokeAllSequential(@Nullable final List<Callable<Object>> callables) {
+        if(isEmpty(callables)) {
+            return Collections.emptyList();
+        }
+        try {
+            return sequentialExecutor.invokeAll(callables);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+    
     public static ThreadPoolSupport getInstance() {
         return _Context.computeIfAbsent(ThreadPoolSupport.class, __-> new ThreadPoolSupport());
     }
 
     @Override
     public void close() throws Exception {
-        executor.shutdown();
+        try {
+            executor.shutdown();
+        } finally {
+            // in case the previous throws, continue execution here
+            sequentialExecutor.shutdown();            
+        }
     }
 
 }