当前位置: 首页 > 知识库问答 >
问题:

ExecutorService与临时线程生成器

弘烨烁
2023-03-14

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

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

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

这只是一种方式比另一种方式执行工作更快的问题吗?

这里有两个非常简单的例子来说明这两种方式之间的区别:

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

使用executor服务:计数器(任务)

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;
    } 
}

使用executor服务:(创建、提交)

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

共有1个答案

袁永贞
2023-03-14

虽然问题和示例代码并不相关,但我将尝试澄清这两个问题。与任意生成线程相比,executorservice的优势在于它的行为可预测,并且避免了线程创建的开销,而创建线程的开销在JVM上相对较大(例如,它需要为每个线程保留内存)。通过可预见性,至少对于fixedthreadpool,我的意思是您知道并发线程的最大数量,并且知道它们可能在何时以及如何创建(因此JVM不会在突然出现峰值的情况下崩溃)。

Vince Emigh:executorservice还支持cachedthreadpool,它没有最大值。人们选择使用executorservice的主要原因是防止创建多个线程(通过使用工作线程)的开销。它主要用于需要在一个单独的线程上执行许多小任务的情况。另外,不要忘记singlethreadexecutor

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

Vince Emigh:runnable也不能抛出异常,而callable可以。

 类似资料:
  • 本文向大家介绍java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例,包括了java多线程CountDownLatch与线程池ThreadPoolExecutor/ExecutorService案例的使用技巧和注意事项,需要的朋友参考一下 1、CountDownLatch: 一个同步工具类,它允许一个或多个线程一直等待,直到其他线

  • 假设我有一个Executors静态工厂方法的ExecutorService实例。 如果我从某个线程提交了一个调用,其中RetVal不是线程安全的本地实例化对象,那么当我从同一个线程获得()它时,我需要担心retvals的完整性吗?人们说局部变量是线程安全的,但我不确定当您返回一个本地实例化的对象并从其他线程接收它时,它是否适用。 下面是我的定制实现,我只是为了测试。您可以忽略EType枚举。

  • 在一个实用程序库中,我正在创建一个执行器服务 然后,主线程将向该服务发布一些任务。当主线程完成时,我想关闭Executor服务,以允许应用程序退出。 问题是我只能更改实用程序库中的代码。我考虑的一个选项是使用守护线程。但在发布到该服务的任务完成之前,它会突然关闭。

  • tempfile 模块专门用于创建临时文件和临时目录,它既可以在 UNIX 平台上运行良好,也可以在 Windows 平台上运行良好。 tempfile 模块中常用的函数,如表 1 所示。 表 1 tempfile 模块常用函数及功能 tempfile 模块函数 功能描述 tempfile.TemporaryFile(mode='w+b', buffering=None, encoding=Non

  • 我从主线程调用了下面的代码,使用ExecutorService池并启动一个线程来处理找到的每个文件。我正在尝试了解当主线程被kill命令终止时ExecutorService的行为。生成的线程会发生什么?一旦完成工作,它们会立即被杀还是终止? 还有没有更好/更安全的方法来编写下面的代码段,特别是如果我在无限循环中运行这部分,例如等待文件被放到输入目录并分配线程来处理它们?在这种情况下,我应该创建一个

  • 问题内容: 我用于创建临时表的语法如下: 我知道这意味着在每笔交易结束时,都会删除该表。我的问题是,如果同一会话上的两个或多个线程创建并将值插入到临时表中,它们将各自获取自己的实例,还是该临时实例在整个会话中共享?如果它是共享的,是否有一种方法可以使每个线程本地化? 感谢Netta 问题答案: 临时表对于同一会话中的所有操作都是可见的。因此,在删除存在的临时表之前(在您的情况下提交事务),您 无法