【问题标题】:Is java ExecutorService newSingleThreadExecutor performs all the tasks using only one Thread?java ExecutorService newSingleThreadExecutor 是否只使用一个线程执行所有任务?
【发布时间】:2018-03-23 05:33:23
【问题描述】:

我知道无法重新启动 java 线程。那么当我向newSingleThreadExecutor提交多个任务时,它是如何使用单线程执行所有任务的呢?

我的理解是 newSingleThreadExecutor 一次最多使用一个线程来处理任何提交的任务。我猜对 newFixedThreadPool 也是如此。 如果一个线程不能重新启动,那么为了执行 n 个任务,应该产生 n 个线程。我认为 newSingleThreadExecutor, newFixedThreadPool 将确保不会同时产生很多线程,就像我们不使用 ExecutorService 一样(我们将每个任务附加到一个线程并单独启动)

这里是代码示例

class Task implements Runnable {
    public void run() {
        System.out.println("ThreadID-" + Thread.currentThread().getId());
        try {
            Thread.sleep(100);
        }
        catch (InterruptedException e) {
        }
    }
}

public class SingleThreadExecutorTest {
    public static void main(String[] args) {
        System.out.println("ThreadID-" + Thread.currentThread().getId());
        ExecutorService ex = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            ex.execute(new Task());
        }
    }
}

上面的代码总是打印相同的 ThreadID。

如果我替换下面的行

Executors.newSingleThreadExecutor();

ExecutorService ex = Executors.newFixedThreadPool(2);

然后它再次能够使用 2 个线程执行所有任务。

仅当我使用时

Executors.newCachedThreadPool();

我看到不同的线程 ID。

ExecutorService 如何重用一个线程? 不让它到达死态吗?

【问题讨论】:

  • 执行器将任务发送到池中,无限循环中的线程检查池中是否有要执行的新任务
  • 所以 newSingleThreadExecutor 将有一个线程,其中 run 方法将运行一个无限循环。提交的 Runnable 对象将进入队列。无限循环将检查队列,轮询 Runnable 对象并调用它的 run 方法。所以这里的Runnable只是用来定义任务。我认为它会使用 Thread(Runnable) 构造函数创建一个 Thread 对象,这很糟糕。

标签: java multithreading


【解决方案1】:

ThreadPoolExecutor 维护一些 Worker 线程,它们的工作方式如下:

public class Demo {

    public class Worker implements Runnable {
        @Override
        public void run() {
            Runnable task = getTaskFromQueue();
            while (task != null) {
                task.run();
                task = getTaskFromQueue();  // This might get blocked if the queue is empty, so the worker thread will not terminate
            }
        }
    }

    public static void main(String[] args) {
        Worker worker = new Worker();
        Thread thread = new Thread(worker);
        thread.start();
    }

}

当您将任务提交给具有单个Worker 线程的ThreadPoolExecutor 时,调用线程将在以下条件下将任务放入BlockingQueue

  • 单身Worker很忙
  • BlockingQueue 未满

Worker 空闲时,它将从此BlockingQueue 检索新任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-10
    • 1970-01-01
    • 2013-01-08
    • 2016-07-23
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-28
    相关资源
    最近更新 更多