如何让ThreadPoolExecutor在Java中立即执行

如何让ThreadPoolExecutor在Java中立即执行,java,multithreading,threadpool,runnable,threadpoolexecutor,Java,Multithreading,Threadpool,Runnable,Threadpoolexecutor,我有一个ThreadPoolExecutor和一个名为this.Runnable的Runnable。我是这样运行的: ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); executor.execute(this.runnable); 通常,this.runnable几乎会立即被调用(100-200us之后)。但有时,如果CPU很忙,它可能需要一段时间才能运行 是否有一种方法可以

我有一个
ThreadPoolExecutor
和一个名为
this.Runnable
Runnable
。我是这样运行的:

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


是否有一种方法可以“强制”立即执行该线程,或者建议JVM/ThreadPoolExecutor优先执行该线程?我需要将它作为一个单独的线程保留,但同时,我需要它以紧急状态开始运行。

您可以尝试增加已创建线程的优先级:

ExecutorService executorService = Executors.newFixedThreadPool(1, runnable -> {
    Thread thread = new Thread(runnable);
    thread.setPriority(Thread.MAX_PRIORITY);
    return thread;
});
是否有一种方法可以“强制”立即执行该线程,或者建议JVM/ThreadPoolExecutor优先执行该线程

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

特别是对于
ThreadPoolExecutor
,当您在
ThreadPoolExecutor
的实例上调用
execute()
时,会说:“在将来某个时候执行给定的任务。”没有提到如何影响或控制线程何时启动

我需要保持它作为一个单独的线程,但同时,我需要它开始运行的紧迫性

也许您可以创建一个线程池,其中有一个(或多个)线程可以运行,并使用Java内置的并发类(如)中的某些内容作为开始执行的方式

更新:下面的示例演示了如何使用信号量“启动”线程

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();
以下是线程本身–它将一个
信号量作为输入,然后等待,直到它能够成功获取它,然后再转到下一个代码:

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对任务进行排队。通过这种方式,高优先级任务可以被赋予队列中的最高位置,以便在工作线程释放后立即运行。但是我不喜欢这个选项,因为它增加了复杂性和开销,低优先级的任务可能会被饿死

在线程优先级上闲逛通常效果不好。不同的平台实现不同的优先级,因此依赖优先级的代码在不同的平台上可能有不同的行为。同时,具有不同优先级的线程也很容易导致错误。以下是本书(10.3.1)中关于优先级的内容:

抵制调整线程优先级的诱惑通常是明智的。一旦您开始修改优先级,则 应用程序的行为变得特定于平台,并且引入了饥饿风险。您经常可以发现一个程序正试图通过以下方式从优先级调整或其他响应问题中恢复: Thread.sleep或Thread.yield调用位于奇数位置,试图为优先级较低的线程提供更多时间

正如其他人之前所说,您无法阻止其他进程使用CPU(您必须将应用程序移动到一个不与其他进程争夺CPU的平台上),也无法强制操作系统调度和运行特定线程

您不必将自己局限于一个线程池。JCIP(8.1)建议:

当任务是同质和独立的时,线程池工作得最好。混合长时间运行和短时间运行的任务有可能“阻塞”池,除非它非常大;提交依赖于其他任务的任务可能会导致死锁,除非池是无界的

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

我要做的是:

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

  • <> LI>

    如果CPU是一个问题,考虑改变应用程序部署的位置,这样就不必与其他进程共享CPU,或者修复主机,这样CPU就越多。

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


决定线程何时运行是操作系统的责任,不能由java代码控制。在您发布的代码中,您只启动了一个线程。你有没有尝试过简单的
new Thread().start()
?@Abra我尝试过,它比使用ThreadPoolExecutor慢。我想知道有什么黑客或方法可以“建议”操作系统优先考虑/强制执行此操作。runnable尽快开始运行。Re“但有时如果CPU忙…”如果应用程序必须在运行其他无关应用程序的同一主机上运行,则无法做太多。如果您需要以亚毫秒的精度控制事件发生的时间,那么您可能需要将其他应用程序从平台中排除,并且您可能需要在实时操作系统(又称“RTOS”)下运行。通常,
this.runnable
几乎会立即被调用。如何获取经过的时间?你到底测量了什么?@Abra在将线程发送到
线程池执行器之前,我记录了历元时间(使用
Instant.now()
),然后在
run
方法开始时再次记录历元时间。当线程开始运行时,使用信号量会加快速度,我需要解决的核心问题是什么?可能是,但取决于你的代码/应用程序在做什么。它似乎值得尝试,并与现有代码的性能进行比较。