Java如何让ThreadPoolExecutor立即执行

How to get ThreadPoolExecutor to execute immediately in Java

我有一个 ThreadPoolExecutor 和一个叫做 this.runnableRunnable。我 运行 是这样的:

ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
executor.execute(this.runnable);

通常,this.runnable 几乎会立即被调用(100-200us 之后)。但有时如果 CPU 很忙,它可能需要一段时间才能 运行。

有没有办法让我 "force" 立即执行,或者建议 JVM/ThreadPoolExecutor 优先执行此线程?我需要将它作为一个单独的线程保留,但同时,我需要它来启动 运行 紧迫性。

您可以尝试提高已创建线程的优先级:

ExecutorService executorService = Executors.newFixedThreadPool(1, runnable -> {
    Thread thread = new Thread(runnable);
    thread.setPriority(Thread.MAX_PRIORITY);
    return thread;
});

Is there a way I can "force" this to execute immediately, or suggest to the JVM/ThreadPoolExecutor to prioritse this thread's execution?

没有。此外,一旦线程启动,您就无法控制它如何继续 运行。您可以设置线程的单独优先级,但这仅在 JVM 决定是 运行 您的线程还是其他一些可能较低优先级的线程时才有用——它不允许您使线程 运行 随时随地。

特别针对 ThreadPoolExecutor,当您在 ThreadPoolExecutor 的实例上调用 execute() 时,Javadoc 表示:"Executes the given task sometime in the future." 没有提及如何影响或控制何时 线程将启动。

I need to keep it as a separate thread but at the same time, I need it to start running with urgency.

也许您可以创建一个线程池,其中有一个(或多个)线程准备就绪,并使用来自 Java 的内置并发性 类 的东西(例如 Semaphore) 作为开始执行的一种方式。

更新:这是一个示例,展示了如何使用信号量来 "start" 线程。

Semaphore semaphore = new Semaphore(0);
new SomeThread(semaphore).start();

// do other things for a while

// when you're ready for the thread to actually start, call "release()" 
semaphore.release();

这是线程本身——它需要一个 Semaphore 作为输入,然后等待它成功获取它,然后再转到下一个代码:

class SomeThread extends Thread {
    private Semaphore semaphore;

    SomeThread(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        try {
            semaphore.acquire();
            // TODO: do the actual thread work here
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

您可以使用 PriorityBlockingQueue 对任务进行排队。这样一来,高优先级任务就可以在队列中排在最高位置,因此一旦有工作人员被释放,它就会 运行s。但我不喜欢这个选项,因为它增加了复杂性和开销,低优先级的任务可能会被饿死。

徘徊在线程优先级上通常效果不佳。不同的平台实现不同的优先级,因此依赖于优先级的代码在不同的平台上可能有不同的行为。同样具有不同优先级的线程很容易导致 priority inversion bug. Here is what the book Java Concurrency in Practice (10.3.1) 不得不说优先级:

It is generally wise to resist the temptation to tweak thread priorities. As soon as you start modifying priorities, the behavior of your application becomes platform-specific and you introduce the risk of starvation. You can often spot a program that is trying to recover from priority tweaking or other responsiveness problems by the presence of Thread.sleep or Thread.yield calls in odd places, in an attempt to give more time to lower-priority threads.

正如其他人之前所说,您无法阻止其他进程使用 CPU(您必须将您的应用程序移动到不与其他进程竞争 [=40] 的平台=]),并且您不能强制 OS 安排和 运行 特定线程。

您不必将自己局限于一个线程池,there are sometimes good reasons to have multiple pools。 JCIP (8.1) 建议:

Thread pools work best when tasks are homogeneous and independent. Mixing long-running and short-running tasks risks "clogging" the pool unless it is very large; submitting tasks that depend on other tasks risks deadlock unless the pool is unbounded.

如果您有一个需要立即执行的短任务,并且它往往会卡在多个较大任务后面排队,那么您需要另一个专用线程池来处理高优先级任务。

我会做什么:

  • 首先,确保线程池在启动时仅初始化一次,并调整线程池的大小以拥有多个线程。只有一个线程,您的任务可能会被另一个线程阻塞。

  • 如果 CPU 是一个问题,请考虑更改应用程序的部署位置,这样它就不必与其他进程共享 CPU,或者修复托管还有更多 CPU 可以去。

  • 如果池仍然是瓶颈,则创建一个单独的线程池作为高优先级任务的快速通道。