在 ExecuterService 中使用线程的 isAlive()、Interrupt() 和 stop() 方法时出现问题

problem using isAlive(),Interrupt() and stop() methods of a Thread inside ExecuterService

我发现在使用 ExecuterService 执行线程时 isAlive() 方法不起作用。 并且 interrupt() 和 stop() 方法也不起作用。
我使用的代码:

Thread t1=new Thread(()->{
    try{
        Thread.sleep(10000);
    } catch(InterruptedExeception ie){
        System.out.println("Interrupted");
    }
    Thread.sleep(5000);
    System.out.println("It's Done");
});
ExecuterService excuter=Executers.newSingleThreadExecuter();
excuter.execute(t1);
Thread.sleep(2000);
System.out.println(t1.isAlive());
Thread.sleep(2000);
t1.interrupt();
t1.stop();

我的预期输出是:

true
Interrupted

实际输出为:

false
It's Done

我需要这种行为的原因。我想知道问题的解决方案是什么,以及 当 Thread 在 ThreadPool 中 运行 时我如何使用这些方法。

  1. stop()方法无效。你不能像这样停止线程。线程需要选择允许自己停止;例如,您将更新一个(volatile 或 AtomicBoolean 样式)布尔值,并且线程 运行 是一个循环,并在每个循环中检查该布尔值;如果它是假的,它就结束了。没有办法在它们的轨道上停止任意线程。完全没有。您可以 google 了解为什么 Thread.stop 被弃用的信息(并且实际上不再有效,即使该方法仍然存在,主要作为文档的载体,说明为什么您不能这样做那个了)。

  2. 线程实现 运行nable,这就是为什么您甚至可以将该线程传递给执行程序方法,但根本不会使用整个线程基础。您应该将此代码更新为 Runnable r = () -> { ... } 并传递它。您编写的代码会误导您认为那是正在 运行 的线程。不是,这就是为什么你得到 false for .isAlive().

  3. 执行者通常不会暴露他们做事的方式,他们只是做事。如果要检查作业是否为 运行ning,请在进入时将(volatile 或 AtomicBoolean)布尔值设置为 true,在退出时设置为 false。或者,如果您真的想使用诸如 .isAlive().

  4. 之类的线程功能,请不要打扰执行程序服务,只需启动线程即可

t1 不是线程。

t1是一个Thread实例,但是Thread实例和线程不是一回事,而且你使用的方式t1,没有线程曾经被创造。将 Thread 实例视为用于创建和控制线程的 handle。如果您的程序调用 t1.start(),将创建该线程,然后 t1.isAlive()t1.interrupt() 以及 t1.stop() 调用都将在该新线程上运行。

除了是一个 Thread 实例之外,t1 也恰好是一个 Runnable 实例,这正是 executer.execute(...) 调用所需要的。作为 Runnable 只意味着 t1 有一个 run() 方法。 run() 方法有多种调用方式:

  • 您可以启动线程,t1.start(),在这种情况下,新线程会调用它,
  • 你可以(你做过)给Executor。当您这样做时,执行器会安排其 工作线程之一 调用您的 run() 方法。
  • 您可以简单地调用它 -- t1.run() -- 这与调用您的代码定义的任何其他方法没有什么不同。
  • 您可以将它传递给任何其他需要 Runnable 的库方法。 (不知道有多少,应该很多吧。)

如果您希望在您的代码可以控制的线程中调用 t1.run(),请调用 t1.start() 来创建该线程。如果您希望它被执行程序服务调用,您 不应 尝试控制其线程,那么请执行您所做的操作:调用 excuter.execute(t1);

只是不要两者都做。那可能不是你想要的。


P.S., 如果您想继续使用 Executor 服务,那么您可能应该更改 t1 的声明。因为在那种情况下它只需要是一个 Runnable ,你可以写:

Thread t1=new Runnable(()->{
    ...
});

这样,阅读您代码的人就不会摸不着头脑,怀疑您是否知道自己在做什么。