smile.util.MulticoreExecutor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
/*******************************************************************************
* Copyright (c) 2010 Haifeng Li
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package smile.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
/**
* Utility class to run tasks in a thread pool on multi-core systems.
*
* @author Haifeng Li
*/
public class MulticoreExecutor {
/** Utility classes should not have public constructors. */
private MulticoreExecutor() {
}
/**
* The number of processors.
*/
private static int nprocs = -1;
/**
* Thread pool.
*/
private static ThreadPoolExecutor threads = null;
/** Creates the worker thread pool. */
private static void createThreadPool() {
if (nprocs == -1) {
int n = -1;
try {
String env = System.getProperty("smile.threads");
if (env != null) {
n = Integer.parseInt(env);
}
} catch (Exception ex) {
System.err.println("Failed to create multi-core execution thread pool:"+ ex);
}
if (n < 1) {
nprocs = Runtime.getRuntime().availableProcessors();
} else {
nprocs = n;
}
if (nprocs > 1) {
threads = (ThreadPoolExecutor) Executors.newFixedThreadPool(nprocs, new SimpleDeamonThreadFactory());
}
}
}
/**
* Returns the number of threads in the thread pool. 0 and 1 mean no thread pool.
* @return the number of threads in the thread pool
*/
public static int getThreadPoolSize() {
createThreadPool();
return nprocs;
}
/**
* Executes the given tasks serially or parallel depending on the number
* of cores of the system. Returns a list of result objects of each task.
* The results of this method are undefined if the given collection is
* modified while this operation is in progress.
* @param tasks the collection of tasks.
* @return a list of result objects in the same sequential order as
* produced by the iterator for the given task list.
* @throws Exception if unable to compute a result.
*/
public static List run(Collection extends Callable> tasks) throws Exception {
createThreadPool();
List results = new ArrayList<>();
if (threads == null) {
for (Callable task : tasks) {
results.add(task.call());
}
} else {
if (threads.getActiveCount() < nprocs) {
List> futures = threads.invokeAll(tasks);
for (Future future : futures) {
results.add(future.get());
}
} else {
// Thread pool is busy. Just run in the caller's thread.
for (Callable task : tasks) {
results.add(task.call());
}
}
}
return results;
}
/**
* Shutdown the thread pool.
*/
public static void shutdown() {
if (threads != null) {
threads.shutdown();
}
}
}