]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.utils.thread/src/org/simantics/utils/threads/ExecutorWorker.java
Allow ExecutorWorker thread pool shutdown
[simantics/platform.git] / bundles / org.simantics.utils.thread / src / org / simantics / utils / threads / ExecutorWorker.java
index e63b304e9e27c7df7ca58f2efbea9ac7daa3a2ee..698d99e97a036fa8305761132ebb60162b4fefbb 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -8,58 +8,71 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - added shutdown facilities
  *******************************************************************************/
-/*
- *
- * @author Toni Kalajainen
- */
+
 package org.simantics.utils.threads;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
 
-
+/**
+ * @author Toni Kalajainen
+ * @author Tuukka Lehtonen
+ */
 public class ExecutorWorker {
-       
-       private static ExecutorWorker instance;
-       
-       static class DelayedExecution implements Comparable<DelayedExecution> {
-               Executable executable;
-               long executionTime;
-               @Override
-               public int compareTo(DelayedExecution o) {
-                       if (o.executionTime<executionTime) return -1;
-                       if (o.executionTime>executionTime) return 1;
-                       return 0;
-               }
-       }
 
-       public static ExecutorWorker getInstance()
-       {
-               if (instance == null)
-                       instance = new ExecutorWorker();
+       private static volatile ExecutorWorker instance;
+
+       public static ExecutorWorker getInstance() {
+               if (instance == null) {
+                       synchronized (ExecutorWorker.class) {
+                               if (instance == null)
+                                       instance = new ExecutorWorker();
+                       }
+               }
                return instance;
        }
-       
-       ExecutorWorker() {              
-       }       
 
-       ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1);
-       
+       private ExecutorWorker() {}
+
+       private final AtomicInteger counter = new AtomicInteger(0);
+       private final ThreadGroup threadGroup = new ThreadGroup("ExecutorWorker-Group");
+       private ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(1, r -> {
+               Thread t = new Thread(threadGroup, r, "ExecutorWorker-" + (counter.incrementAndGet()));
+               if (!t.isDaemon())
+                       t.setDaemon(true);
+               if (t.getPriority() != Thread.NORM_PRIORITY)
+                       t.setPriority(Thread.NORM_PRIORITY);
+               return t;
+       });
+
        public synchronized ScheduledFuture<Object> timerExec(final Executable executable, int delay)
        {
-               Callable<Object> c = new Callable<Object>() {
-                       @Override
-                       public Object call() throws Exception {
-                // FIXME: executable.runnable gets called twice!
-                               ThreadUtils.asyncExec(executable.threadAccess, executable.runnable);
-                               //executable.runnable.run();
-                               return null;
-                       }
-               };              
+               Callable<Object> c = () -> {
+                       ThreadUtils.asyncExec(executable.threadAccess, executable.runnable);
+                       return null;
+               };
                return pool.schedule(c, delay, TimeUnit.MILLISECONDS);
        }
 
+       private void shutdownThis() {
+               ScheduledThreadPoolExecutor e = pool;
+               if (e != null) {
+                       pool = null;
+                       ThreadUtils.shutdownAndAwaitTermination(e, 1000);
+               }
+       }
+
+       public static synchronized void shutdown() {
+               ExecutorWorker i = instance;
+               if (i != null) {
+                       instance = null;
+                       i.shutdownThis();
+               }
+       }
+
 }