org.testng.internal.PoolService Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of testng Show documentation
Show all versions of testng Show documentation
Testing framework for Java
package org.testng.internal;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* This class allows a caller to pass a list of Callable workers that will be run in threads
* taken from the thread pool. Each list of callables is indexed with a key, and when they
* have all completed, the listener passed in @code{submitTask} will be invoked with all
* the futures. Additional workers can be submitted to this pool while it is in existence
* and the caller can either block while waiting for the results (@code{submitTasksAndWait})
* or submit them asynchronously (@code{submitTasks}) and supply listeners to notify when
* the callers are done.
*
* @author cbeust
*
* @param The type of the key to index each list of Callables
* @param The type of the result returned by the futures
*/
public class PoolService {
private static PoolService m_instance;
private ExecutorService m_service;
private HashMap>> m_futureMap;
private Thread m_listenerThread;
private Map> m_listeners;
/**
* One pool is created per XmlSuite object.
*
* @param threadPoolSize the size of the thread pool
*/
private PoolService(int threadPoolSize) {
m_instance = this;
m_service = Executors.newFixedThreadPool(threadPoolSize);
m_futureMap = new HashMap>>();
m_listeners = Maps.newHashMap();
m_listenerThread = new Thread() {
public void run() {
System.out.println("Listener thread starting, futures:" + m_futureMap.size());
while (m_futureMap.size() > 0) {
List doneFutures = Lists.newArrayList();
for (KeyType key : m_futureMap.keySet()) {
List> futures = m_futureMap.get(key);
if (isFinished(futures)) {
PoolListener listener = m_listeners.get(key);
if (listener != null) {
listener.onFinish(key, futures);
}
m_listeners.remove(key);
doneFutures.add(key);
}
}
for (KeyType key : doneFutures) {
m_futureMap.remove(key);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Listener thread ending");
}
};
}
public static void initialize(int threadCount) {
m_instance = new PoolService(threadCount);
}
public static PoolService getInstance() {
if (m_instance == null) {
throw new RuntimeException("The Service Pool was not created, should never happen");
}
return m_instance;
}
/**
* This listener will be invoked as soon as all the Callables in a given list have completed.
*/
public static interface PoolListener {
public void onFinish(KeyType key, List> results);
}
/**
* Submit the tasks to the thread pool.
*/
public List submitTasksAndWait(KeyType key, List> tasks) {
submitTasks(key, tasks, null);
List> futures = m_futureMap.get(key);
while (!isFinished(futures)) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
List result = Lists.newArrayList();
for (Future future : futures) {
try {
result.add(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return result;
}
public void submitTasks(KeyType key, List> tasks,
PoolListener listener) {
for (Callable task : tasks) {
Future future = m_service.submit(task);
List> list = m_futureMap.get(key);
if (list == null) {
list = Lists.newArrayList();
m_futureMap.put(key, list);
}
list.add(future);
}
if (listener != null) {
m_listeners.put(key, listener);
if (!m_listenerThread.isAlive()) {
m_listenerThread.start();
}
}
}
private boolean isFinished(List> futures) {
for (Future f : futures) {
if (!f.isDone())
return false;
}
return true;
}
/**
* Shut down the service.
*/
public void shutdown() {
Utils.log(getClass().getName(), 3, "Shutting down poolservice " + this + " terminated:"
+ m_service.isTerminated());
// if (m_service.isTerminated()) {
m_service.shutdown();
// }
}
}