等待线程在java

时间:2018-02-14 09:29:46

标签: java threadpool executorservice

我在JAVA中使用executorservice进行线程池化。有没有一种方法可以让我在执行服务中的线程池中等待线程可用,并且仅在池中有可用线程时才继续

2 个答案:

答案 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)

这是一个任务示例,该任务使用ThreadPool并使线程提交工作在有太多等待可用线程的工作时等待工作

这在列出[要做的事情]便宜而[做]的工作很耗时的情况下很有用。

例如:

  • 运行CPU密集型任务时,有很多可用的CPU。
  • 当您运行依赖于几个慢速API或数据源的任务时。

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();

    }
}