Java ExecutorService与临时线程产卵器

Java ExecutorService与临时线程产卵器,java,multithreading,executorservice,Java,Multithreading,Executorservice,我有一个关于ExecutorService在Java中如何工作的基本问题 很难看出简单地创建线程来并行执行某些任务与将每个任务分配给线程池之间的区别 ExecutorService看起来也非常简单高效,所以我想知道为什么我们不一直使用它 这仅仅是一种方式比另一种方式更快地执行其任务的问题吗 下面是两个非常简单的示例来说明这两种方法之间的区别: 使用executor服务:Hello World(任务) static class HelloTask implements Runnable {

我有一个关于
ExecutorService
在Java中如何工作的基本问题

很难看出简单地创建
线程来并行执行某些任务与将每个任务分配给
线程池
之间的区别

ExecutorService
看起来也非常简单高效,所以我想知道为什么我们不一直使用它

这仅仅是一种方式比另一种方式更快地执行其任务的问题吗

下面是两个非常简单的示例来说明这两种方法之间的区别:

使用executor服务:Hello World(任务)

static class HelloTask implements Runnable {
    String msg;

    public HelloTask(String msg) {
        this.msg = msg; 
    }
    public void run() {
        long id = Thread.currentThread().getId();
        System.out.println(msg + " from thread:" + id);
    }
}
使用executor服务:Hello World(创建executor,提交)

静态类HelloTask{
公共静态void main(字符串[]args){
int ntasks=1000;
ExecutorService exs=Executors.newFixedThreadPool(4);

对于(inti=0;i,当问题和示例代码不相关时,我将尝试澄清两者。 与随意生成线程相比,
ExecutorService
的优势在于,它的行为是可预测的,并避免了在JVM上相对较大的线程创建开销(例如,它需要为每个线程保留内存).说到可预测性,至少对于
fixedThreadPool
,我的意思是您知道并发线程的最大数量,并且您知道何时以及如何创建它们(这样您的JVM不会在突然出现峰值时崩溃)

文斯·埃米尔:
ExecutorService
还支持
cachedThreadPool
,它没有 最大值。人们选择使用执行器服务的主要原因是 防止创建多个线程的开销(通过使用辅助线程) 线程)。它主要用于需要执行许多小任务的情况 在单独的线程上执行。另外,不要忘记
singleThreadExecutor

现在,关于
Runnable
vs
Callable
,很容易从您的示例中看出。
Callable
s可以返回一个值占位符(
Future
),该值占位符最终将由将来的实际值填充。
Runnable
s不能返回任何内容

文斯·埃米尔:
Runnable
也不能抛出异常,而
Callable
可以抛出异常

与普通线程相比,提供了许多优势

  • 您可以创建/管理/控制线程的生命周期,并优化线程创建成本开销
  • 您可以控制任务的处理(工作窃取、ForkJoinPool、invokeAll)等
  • 您可以在将来安排任务
  • 您可以监视线程的进度和运行状况
  • 即使对于单个线程,我也更喜欢使用
    Executors.newFixedThreadPool(1);

    查看相关SE问题:


    这两个示例都使用
    ExecutorService
    而不是创建新线程,因此我不确定在这种情况下,您在这两个示例之间比较的是什么。您对何时使用
    Runnable
    和何时使用
    Callable
    感到困惑吗?
    static class HelloTask {
        public static void main(String[] args) {
            int ntasks = 1000;
            ExecutorService exs = Executors.newFixedThreadPool(4);
    
            for (int i=0; i<ntasks; i++) { 
                HelloTask t = new HelloTask("Hello from task " + i);    
                exs.submit(t);
            }
            exs.shutdown();
        }
    }
    
    static class HelloTaskRet implements Callable<Long> {
        String msg;
    
        public HelloTaskRet(String msg) {
            this.msg = msg; }
    
            public Long call() {
            long tid = Thread.currentThread().getId(); 
            System.out.println(msg + " from thread:" + tid); 
            return tid;
        } 
    }
    
    static class HelloTaskRet {
        public static void main(String[] args) {
            int ntasks = 1000;
            ExecutorService exs = Executors.newFixedThreadPool(4);
    
            Future<Long>[] futures = (Future<Long>[]) new Future[ntasks];
    
            for (int i=0; i<ntasks; i++) { 
                HelloTaskRet t = new HelloTaskRet("Hello from task " + i);
                futures[i] = exs.submit(t);
            }
            exs.shutdown();
        }
    }