当前位置: 首页 > 知识库问答 >
问题:

java 多个线程正在运行,当一个线程找到解决方案时停止线程

柳英豪
2023-03-14

我在尝试停止运行多个线程的程序时遇到了问题,所有运行的线程都试图找到相同的解决方案,但一旦一个线程找到了解决方案,所有其他线程都将停止。

在main方法中,我创建了一个线程组,使用for循环向其中添加线程并启动它们

ThreadGroup tg = new ThreadGroup("thread group");
Thread th;
for(int i  = 0; i<4; i++){
  th = new Thread(tg, new Runnable(), "Thread " + i)
  th.start();
}

在实现Runnable的类中,我很难找出如何使其实现,以便一旦其中一个线程找到解决方案,所有线程都将停止。最终发生的情况是,要么其他线程继续运行,有时这些线程会相互中断并相互覆盖。

共有3个答案

锺伟志
2023-03-14
ThreadGroup tg = new ThreadGroup("thread group");
CountDownLatch latch = new CountDownLatch(1);
AtomicInteger result = new AtomicInteger();
Random random = new Random();
for (int i = 0; i < 4; i++) {
    Thread th = new Thread(tg, () -> {
        try {
            Thread.sleep(random.nextInt(10000));
            result.set(42);
            latch.countDown();
            System.out.println(Thread.currentThread().getName() + " completed task first");
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + " was interrupted before it could finish the task");
        }
    }, "Thread " + i);
    th.start();
}
while (latch.getCount() > 0) {
    try {
        latch.await();
    } catch (InterruptedException ignored) {
    }
}
tg.interrupt();
System.out.println("The result is " + result.get());

示例显示如何等待线程完成。

您需要确保您的操作是可中断的。Thread.sleep如本例所示,默认情况下是可中断的。有关更多信息,请参阅oracle文档。

还要注意,不可能保证所有其他线程在完成之前都会被中断。如果您需要确保只处理一个结果,请同步对结果变量的访问,并放弃第一个结果之后的任何更改。

令狐宣
2023-03-14

当意识到已经找到解决方案时,获胜的线程应该向父线程发出信号——然后父线程向所有其他子线程发出停止信号,或者直接杀死它们。

吕翰飞
2023-03-14

您必须中断这些线程(并处理可运行的中断)。我也不确定您是否应该使用ThreadGroup-我记得看到过有关它们的Sonar警告。

您可能最好使用ExecutorService并使用 CountDownLatch(这是一种实现方法):

ExecutorService es = Executors.newFixedThreadPool(100);
CountDownLatch cdl = new CountDownLatch(1);
for (int i = 0; i < 100; ++i) {
  es.submit(() -> {
    Thread.sleep(TimeUnit.SECONDS.toMillis(30)); // + exception handling  
    cdl.countDown();
  });
}
cdl.await(); // or await(5, TimeUnit.MINUTES);
es.shutdownNow();

诀窍是:

  1. 您创建一个ExecutorService,其中包含100个线程池
  2. 您创建一个CoundDownLatch-一个屏障-计数为1。
  3. 你提交你的任务,当他们的工作完成时,调用cdl.countDown();将计数器从1减少到0。
  4. 父线程等待CountDownLatch减少到0-您可能应该使用第二个版本(例如阻塞到5分钟)。

如果所有的< code>Runnable都失败,则不会有结果:要么使用最大等待时间,要么添加另一个< code>CountDownLatch,这次计数为100(线程数),在< code>try/finally中使用< code>countDown(),在另一个线程中,中断在< code>cdl上等待的线程。你也可以在一个循环中这样做:

CountDownLatch allCdl = new CountDownLatch(100);

for (;allCdl.getCount() != 0;) {
  if (!cdl.await(60, TimeUnit.SECONDS)) {
    if (allCdl.getCount() == 0) { 
      break;
    }
  }
}

但是,getCount()的javadoc提到此方法通常用于调试和测试目的。(参见CyclicBarrier)。不确定这是否是正确的用法。

 类似资料:
  • 我正在为这个问题寻找一个干净的设计/解决方案:我有两个线程,可以运行用户想要的时间,但最终会在用户发出停止命令时停止。然而,如果其中一个线程突然终止(例如,由于运行时异常),我想停止另一个线程。 现在,这两个线程都执行一个(因此,当我说“stop a thread”时,我的意思是对实例调用一个stop()方法),我想的是避免使用线程(thread类),并使用interface,然后将这两个Runn

  • 以下是问题陈述: 编写一个java程序,使用线程计算前25个素数,并计算前50个斐波那契数。将计算斐波那契数的线程的优先级设置为8,将另一个设置为5。在计算了30个斐波那契数之后,让这个线程进入睡眠状态,开始计算素数。计算完25个素数后,继续斐波那契数计算。 我的代码: 我本以为当斐波那契线停止时,其余的素数会被打印出来,但那没有发生,这背后的原因可能是什么?

  • 我如何启动两个线程,其中thread1首先执行,thread2在thread1结束时启动,而主方法线程可以在不锁定其他两个线程的情况下继续工作? 我尝试了join(),但是它需要从线程调用,线程必须等待另一个线程,没有办法执行类似thread2.join(thread1)的操作;因此,如果我在main()中调用join,我将有效地停止主线程的执行,而不仅仅是Thread2的执行。 #编辑:为什么我

  • 问题内容: 我在Java中的线程上有些挣扎,我有三个线程- 线程1,线程2和线程3。那些启动时正在执行某些任务,我想通过thread1停止这两个线程。我将thread1放在,然后停止两个线程,但是两个线程的进程仍在运行。你有什么想法吗? 问题答案: 您如何试图阻止他们??警告此方法已弃用。 而是考虑对线程1使用某种标志来与线程2和3通信,它们应该停止。实际上,您可能会使用interrupts。 下

  • 我有一个带有静态ConcurrentQueue的类。一个类接收消息并将其放入队列中,而这个类上的另一个线程从该队列中读取消息并一次处理一个。使用cancellationtoken中止该方法。 清空队列的方法如下所示: 我的测试方法如下: 因此,我在自己的线程中启动我的出列方法,并使用一个新的取消令牌。然后我将一些消息排队,给进程一秒钟时间来处理它们,然后使用源代码。Cancel(false)结束线

  • 问题内容: 因此,我的目标是让函数启动自己的线程,以便可以并行运行,而不必等待上一个线程完成。问题在于,它似乎不是多线程的(意味着一个线程在另一个线程开始之前就完成了)。 我也有该函数的内部,但似乎启动的线程的标识与从其运行python脚本的主线程相同。我认为我的方法不正确。 问题答案: 这是常见错误,容易出错。 只需在主线程中一次执行您的函数,然后将(我想为您函数的返回值)作为函数传递给线程,这