【发布时间】:2018-07-24 19:40:42
【问题描述】:
我在 JAVA 中使用 executorservice 进行线程池。有没有一种方法可以让我在执行器服务的线程池中等待线程可用,并且只有在池中有可用线程时才继续
【问题讨论】:
标签: java threadpool executorservice
我在 JAVA 中使用 executorservice 进行线程池。有没有一种方法可以让我在执行器服务的线程池中等待线程可用,并且只有在池中有可用线程时才继续
【问题讨论】:
标签: java threadpool executorservice
拥有 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() 返回时,池中的线程理论上是可用的,但它会立即被执行程序重用以运行下一个等待任务。
【讨论】:
这在列出 [做什么] 成本低且 [做什么] 耗时的情况下很有用。
例如:
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();
}
}
【讨论】: