@@ -0,0 +1,3111 @@
+package org.helioviewer.jhv.threads;%0A%0Aimport java.lang.ref.WeakReference;%0Aimport java.security.AccessController;%0Aimport java.beans.PropertyChangeListener;%0Aimport java.beans.PropertyChangeEvent;%0Aimport java.util.concurrent.*;%0Aimport java.security.PrivilegedAction;%0A%0Aimport javax.swing.SwingWorker;%0A%0Aimport sun.awt.AppContext;%0A%0Apublic class JHVExecutor %7B%0A%0A    public static synchronized ExecutorService getWorkersExecutorService(int MAX_WORKER_THREADS) %7B%0A       final AppContext appContext = AppContext.getAppContext();%0A       ExecutorService executorService =%0A           (ExecutorService) appContext.get(SwingWorker.class);%0A       if (executorService == null) %7B%0A           //this creates daemon threads.%0A           ThreadFactory threadFactory =%0A               new ThreadFactory() %7B%0A                   final ThreadFactory defaultFactory =%0A                       Executors.defaultThreadFactory();%0A                   public Thread newThread(final Runnable r) %7B%0A                       Thread thread =%0A                           defaultFactory.newThread(r);%0A                       thread.setName(%22JHVWorker-%22%0A                           + thread.getName());%0A                       thread.setDaemon(true);%0A                       return thread;%0A                   %7D%0A               %7D;%0A%0A           executorService =%0A               new ThreadPoolExecutor(MAX_WORKER_THREADS, MAX_WORKER_THREADS,%0A                                      10L, TimeUnit.MINUTES,%0A                                      new LinkedBlockingQueue%3CRunnable%3E(),%0A                                      threadFactory);%0A           appContext.put(SwingWorker.class, executorService);%0A%0A           // Don't use ShutdownHook here as it's not enough. We should track%0A           // AppContext disposal instead of JVM shutdown, see 6799345 for details%0A           final ExecutorService es = executorService;%0A           appContext.addPropertyChangeListener(AppContext.DISPOSED_PROPERTY_NAME,%0A               new PropertyChangeListener() %7B%0A                   @Override%0A                   public void propertyChange(PropertyChangeEvent pce) %7B%0A                       boolean disposed = (Boolean)pce.getNewValue();%0A                       if (disposed) %7B%0A                           final WeakReference%3CExecutorService%3E executorServiceRef =%0A                               new WeakReference%3CExecutorService%3E(es);%0A                           final ExecutorService executorService =%0A                               executorServiceRef.get();%0A                           if (executorService != null) %7B%0A                               AccessController.doPrivileged(%0A                                   new PrivilegedAction%3CVoid%3E() %7B%0A                                       public Void run() %7B%0A                                           executorService.shutdown();%0A                                           return null;%0A                                       %7D%0A                                   %7D%0A                               );%0A                           %7D%0A                       %7D%0A                   %7D%0A               %7D%0A           );%0A       %7D%0A       return executorService;%0A   %7D%0A%0A%7D%0A

Add JHVExecutor