发送到 scheduleAtFixedRate 时线程名称不匹配

Thread name does not match when sending it to scheduleAtFixedRate

我创建了一个可运行的 class 并创建了一个线程,但具有唯一的名称,但是当我通过 executor.scheduleAtFixedRate 发送该线程时,它创建了自己的线程,我不明白这是为什么?

我试着阅读这里,但我还是不明白: https://www.codejava.net/java-core/concurrency/java-concurrency-scheduling-tasks-to-execute-after-a-given-delay-or-periodically

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        ScheduledExecutorService executor =
                Executors.newSingleThreadScheduledExecutor();
        Runnable runnable = new AutoUpdater();
        Thread thread = new Thread(runnable, "MyThread");
        executor.scheduleAtFixedRate(thread, 0, 24, TimeUnit.HOURS);
    }
}

public class AutoUpdater implements Runnable {
    public void run() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " is running...");
        System.out.println("Thread ended.\n");
    }
}

它应该打印名称 MyThread 但输出是:

pool-1-thread-1

它应该是这样的:

pool-1-MyThread-1

执行者服务正在为您创建它。 如果你想覆盖线程的命名,你可以在执行程序服务中设置选项。 参见 Naming threads and thread-pools of ExecutorService

问题是 Executors.newSingleThreadScheduledExecutor() 创建了一个内部有自己线程的池。

当您查看 ScheduledExecutorService::scheduleAtFixedRate it takes Runnable as first argument. And this Runnable will be run by some thread from the pool. Notice that Thread 实现 Runnable 并将 Thread 实例传递给 scheduleAtFixedRate 方法时,此线程的 运行 方法将被调用一些其他线程 但您传递的线程将不会启动 。一般来说,为了避免任何误解,您应该在此处传递简单的 Runnable,这将代表需要完成的工作。

如果您想更改此池中线程的名称,您必须提供自定义 ThreadFactory,池将使用它来创建新线程:

ThreadFactory threadFactory = runnable -> new Thread(runnable, "MyThreadName");

ScheduledExecutorService executor =
            Executors.newSingleThreadScheduledExecutor(threadFactory);

编辑 :

对于 Java 小于 8 的版本,我们可以简单地创建新的 class 实现 ThreadFactory 接口:

class MyThreadFactory implements ThreadFactory {
    @Override
    public Thread newThread(Runnable runnable) {
        return new Thread(runnable, "MyThreadName");
    }
}

然后传过去:

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new MyThreadFactory());