/*******************************************************************************
- * 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
*
* 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();
+ }
+ }
+
}