package com.neocoretechs.bigsack.io; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadFactory; /** * Class to manage thread resources throughout the application. Singleton * Usage pattern is ThreadPoolManager.getInstance().spin([your Runnable]) * ThreadPoolManager.shutdown() shuts all groups * ThreadPoolManager.shutdown([group]) shuts down named group * The default group is determined by constant DEFAULT_THREAD_POOL and is used when no arguments are provided in overloaded methods * additional groups may be named using init() and an array containing group names * Copyright 2014 NeoCoreTechs * @author jg * */ public class ThreadPoolManager { private static final boolean DEBUG = false; private static String DEFAULT_THREAD_POOL = "SACKIO"; private int threadNum = 0; private static Map<String, ExecutorService> executor = new HashMap<String, ExecutorService>();// = Executors.newCachedThreadPool(dtf); public static ThreadPoolManager threadPoolManager = null; private ThreadPoolManager() { } public static ThreadPoolManager getInstance() { if( threadPoolManager == null ) { threadPoolManager = new ThreadPoolManager(); // set up pool for system processes executor.put(DEFAULT_THREAD_POOL, Executors.newCachedThreadPool(getInstance().new LocalThreadFactory(DEFAULT_THREAD_POOL))); } return threadPoolManager; } /** * Update the array of Executors that manage a cached thread pool for * reading topics. One thread pool per topic to notify listeners of data ready. * In each appropriate place, ThreadPoolmanager.init("group") may be called to add "group" to the * list of known thread group names. The names are continually appended throughout the run. * @param threadGroupNames The topics for which thread groups are established */ public static void init(String[] threadGroupNames, boolean overWrite) { for(String tgn : threadGroupNames) { if(!overWrite) { if( executor.containsKey(tgn)) continue; } executor.put(tgn, Executors.newCachedThreadPool(getInstance().new LocalThreadFactory(tgn))); } } public void waitGroup(String group) { try { ExecutorService w = executor.get(group); synchronized(w) { w.wait(); } } catch (InterruptedException e) { } } public void waitGroup(String group, long millis) { try { ExecutorService w = executor.get(group); synchronized(w) { w.wait(millis); } } catch (InterruptedException e) { } } public void notifyGroup(String group) { ExecutorService w = executor.get(group); synchronized(w) { w.notifyAll(); } } public void spin(Runnable r, ThreadGroup group) { executor.get(group.getName()).execute(r); } public void spin(Runnable r, String group) { executor.get(group).execute(r); } public void spin(Runnable r) { executor.get(DEFAULT_THREAD_POOL).execute(r); } public void shutdown() { Collection<ExecutorService> ex = executor.values(); for(ExecutorService e : ex) { List<Runnable> spun = e.shutdownNow(); for(Runnable rs : spun) { if( DEBUG ) System.out.println("Marked for Termination:"+rs.toString()+" "+e.toString()); } } } public void shutdown(String group) { ExecutorService ex = executor.get(group); List<Runnable> spun = ex.shutdownNow(); for(Runnable rs : spun) { if( DEBUG ) System.out.println("Marked for Termination:"+rs.toString()+" "+ex.toString()); } } /** * Submits a Runnable task for execution and returns a Future representing * that task. * * @param task a Runnable task for execution * * @return a Future representing the task */ public static Future<?> submit(Runnable task) { return executor.get(DEFAULT_THREAD_POOL).submit(task); } /** * Submits a Runnable task for execution and returns a Future representing * that task. * @param group The thread group to submit to * @param task a Runnable task for execution * @return a Future representing the task */ public static Future<?> submit(String group, Runnable task) { return executor.get(group).submit(task); } /** * Waits for all threads to complete computation. * * @param futures array of Future objects */ public static void waitForCompletion(Future<?>[] futures) { System.out.println("waitForCompletion on:"+futures.length); int size = futures.length; try { for (int j = 0; j < size; j++) { futures[j].get(); } } catch (ExecutionException ex) { ex.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } class LocalThreadFactory implements ThreadFactory { ThreadGroup threadGroup; public LocalThreadFactory(String threadGroupName) { threadGroup = new ThreadGroup(threadGroupName); } public ThreadGroup getThreadGroup() { return threadGroup; } public Thread newThread(Runnable r) { Thread thread = new Thread(threadGroup, r, threadGroup.getName()+(++threadNum)); //thread.setDaemon(true); return thread; } } }