我在JAVA中使用executorservice进行线程池化。有没有一种方法可以让我在执行服务中的线程池中等待线程可用,并且仅在池中有可用线程时才继续
答案 0 :(得分:0)
拥有ExecutorService的重点不在于处理线程,所以除非你有一个非常具体的理由来跟踪它们的状态,否则你应该避免这样做。
此外,您可以向池中添加任意数量的任务,执行程序将全部运行它们。
例如:
final List<Callable<Boolean>> tasks = new ArrayList<>(10);
for (int i=0;i<10;i++) tasks.add(()->{
//something time consuming
return true;
});
final ExecutorService executor = Executors.newFixedThreadPool(5);
List<Future<Boolean> handles = executor.invokeAll(tasks);
for (Future<Boolean> handle : handles) {
handle.get();
}
// here all the 10 tasks have been completed by the 5 thread pool
请注意,每次调用handle.get()返回时,池中的线程理论上都可用,但执行程序将立即重用它来运行下一个等待任务。
答案 1 :(得分:0)
这在列出[要做的事情]便宜而[做]的工作很耗时的情况下很有用。
例如:
Java ThreadPools似乎是为开发人员设计的,可以分批提交工作并等待结果(通过Future.get或ThreadPool.shutdown)。没有具有阻塞行为的直接队列大小控制。我相信这是@Francesco Rogo试图向您解释的内容。但是有解决方法。我发现更容易自定义线程池以限制工作队列的大小,并使提交工作的线程等待。我怀疑你也想要那个。
package lucas.examples.threadPool;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ExampleThreadPool {
public static void main( String[] args ) {
// Example resources:
// ThreadLocal<Sql> db001 = new ThreadLocal<Sql>() { protected Sql initialValue() { return DataSource001.instance.get(); }
// ThreadLocal<Sql> db002 = new ThreadLocal<Sql>() { protected Sql initialValue() { return DataSource002.instance.get(); }
ThreadPoolExecutor pool = new ThreadPoolExecutor(
/*nThreads=*/15, /*nThreads=*/15,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>( /*work queue size=*/ 1 )
);
// Setup a thread factory to close the resources
pool.setThreadFactory( (r) -> {
return new Thread( () -> {
r.run();
// Sql.close( db001 )
// Sql.close( db002 )
});
} );
// When the work queue is full, make the thread calling pool.execute() to wait
pool.setRejectedExecutionHandler(
(runnable,executor) -> {
try {
executor.getQueue().put(runnable);
} catch( Exception e ) {
throw new RuntimeException(e);
}
}
);
// Simulates a work datasource
for( int i = 0; i < 1000000; i++ ) {
int i2 = i;
System.out.println( "submit work..." + i2 );
pool.execute( () -> {
// start parallel processing
System.out.println( "begin execution of work..." + i2 );
try { Thread.sleep(500); } catch( Exception e ) { }
System.out.println( "end execution of work..." + i2 );
// end parallel processing
} );
}
// IMPORTANT: wait all threads to finish the work before ending the program
pool.shutdown();
}
}