【问题标题】:How to stop a thread by another thread?如何通过另一个线程停止一个线程?
【发布时间】:2012-08-07 05:41:00
【问题描述】:

我在 Java 中遇到了一些线程问题,我有三个线程 - thread1、thread2 和 thread3。那些在启动时正在执行一些任务,我想通过 thread1 停止这两个线程。我把thread1为sleep(500),然后我停止了两个线程,但是两个线程的进程还在运行。你知道怎么做吗?

【问题讨论】:

  • 有一些代码作为例子吗??

标签: java multithreading


【解决方案1】:

你打算如何阻止他们? Thread.stop?请注意,此方法已被弃用。

相反,请考虑为线程 1 使用某种标志来与线程 2 和 3 进行通信,表明它们应该停止。事实上,你或许可以使用interrupts

下面,Thread.interrupt 用于实现协调。

final Thread subject1 = new Thread(new Runnable() {

  public void run() {
    while (!Thread.interrupted()) {
      Thread.yield();
    }
    System.out.println("subject 1 stopped!");
  }
});
final Thread subject2 = new Thread(new Runnable() {

  public void run() {
    while (!Thread.interrupted()) {
      Thread.yield();
    }
    System.out.println("subject 2 stopped!");
  }
});
final Thread coordinator = new Thread(new Runnable() {

  public void run() {
    try {
      Thread.sleep(500);
    } catch (InterruptedException ex) { }
    System.out.println("coordinator stopping!");
    subject1.interrupt();
    subject2.interrupt();
  }
});
subject1.start();
subject2.start();
coordinator.start();

或者,您也可以使用volatile boolean(或AtomicBoolean)作为交流方式。 volatilejava.util.concurrent.atomic.* 提供的 Atomic access 允许您确保主题线程可以看到标志的变化。

final AtomicBoolean running = new AtomicBoolean(true);

final ExecutorService subjects = Executors.newFixedThreadPool(2);
subjects.submit(new Runnable() {

  public void run() {
    while (running.get()) {
      Thread.yield();
    }
    System.out.println("subject 1 stopped!");
  }
});
subjects.submit(new Runnable() {

  public void run() {
    while (running.get()) {
      Thread.yield();
    }
    System.out.println("subject 2 stopped!");
  }
});
final ScheduledExecutorService coordinator = Executors.newSingleThreadScheduledExecutor();
coordinator.schedule(new Runnable() {

  public void run() {
    System.out.println("coordinator stopping!");
    running.set(false);
    subjects.shutdown();
    coordinator.shutdown();
  }
}, 500, TimeUnit.MILLISECONDS);

同样,您可以选择使用以下字段,而不是使用 AtomicBoolean

static volatile boolean running = true;

更好的是,如果您利用ExecutorServices,您还可以编写类似的代码,如下所示:

final ExecutorService subjects = Executors.newFixedThreadPool(2);
subjects.submit(new Runnable() {

  public void run() {
    while (!Thread.interrupted()) {
      Thread.yield();
    }
    System.out.println("subject 1 stopped!");
  }
});
subjects.submit(new Runnable() {

  public void run() {
    while (!Thread.interrupted()) {
      Thread.yield();
    }
    System.out.println("subject 2 stopped!");
  }
});
final ScheduledExecutorService coordinator = Executors.newSingleThreadScheduledExecutor();
coordinator.schedule(new Runnable() {

  public void run() {
    System.out.println("coordinator stopping!");
    subjects.shutdownNow();
    coordinator.shutdown();
  }
}, 500, TimeUnit.MILLISECONDS);

这利用了ThreadPoolExecutor.shutdownNow 中断其工作线程以尝试发出关闭信号这一事实。


运行任何示例,输出应具有以下效果:

C:\dev\scrap>javac CoordinationTest.java

C:\dev\scrap>java CoordinationTest
coordinator stopping!
subject 1 stopped!
subject 2 stopped!

注意最后两行可以按任意顺序出现。

【讨论】:

    【解决方案2】:

    您不能从另一个线程中停止一个线程。您只能要求线程自行停止,最好的方法是中断它。但是,被中断的线程必须协作,并通过停止执行来尽快响应中断。

    Java tutorial about concurrency 对此进行了介绍。

    【讨论】:

    • “一个线程不能停止另一个线程”(在同一个进程中)是不是只适用于 Java 的一般概念?这是因为只有进程之间的中断才有意义吗?
    【解决方案3】:

    您可以:

    • 有一些线程定期检查的布尔标志。如果它被更改,那么它们将停止执行(注意这可能会导致竞争条件)
    • 另一种选择是使用ExecutorService

    提供方法来管理终止和方法的 Executor 可以产生一个 Future 来跟踪一个或多个的进度 异步任务。

    【讨论】:

    • 初始条件也很重要。所有线程必须开始静音。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多