繁体   English   中英

当其中之一完成工作时,如何停止工作线程?

[英]how to stop worker threads when work is done in one of them?

我正在进行一个简单的模拟,就像破解哈希一样,现在我希望所有其他工作人员中的一个找到结果时停止吗? 除了停止,是否还有其他方法可以停止使用?

import java.util.Random;

class Worker extends Thread{
int target,start,current,end;

public Worker(int target, int start, int end) {
    super();
    this.target = target;
    this.start = start;
    this.end = end;
}

@Override
public void run() {
    current=start;
    while(target!=current){
        System.out.println("Not found  target at "+current);
        current++;
        if(current==end){
            break;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    if(target==current){
        System.out.println(target+" found");
    }
}

}
public class RandomBreak {

public static void main(String[] args) {
    Random r=new Random(100);
    int target=r.nextInt(100);
    System.out.println("trying to search "+target);

    Worker w1=new Worker(target,1,30);
    Worker w2=new Worker(target,30,60);
    Worker w3=new Worker(target,60,90);
    Worker w4=new Worker(target,90,100);
    w1.start();
    w2.start();
    w3.start();
    w4.start();
}

}

当一个线程找到答案时,请在其他线程上调用Thread.interrupt()。 当您捕获InterruptedException时,退出工作线程。

如果您的“真实”代码没有thread.sleep(),那么只需偶尔检查Thread中断标志,例如:

if( Thread.interrupted() ) {
   throw new InterruptedException();
}

使用公共数据结构存储标志,并将数据结构的相同实例传递给每个工作线程。 找到目标的工人将在退出前设置标志。 检查while循环中的标志以及目标。 程式码片段:

public WorkStatus {
    private volatile boolean completed;

    public boolean isCompleted() {
        return completed;
    }

    public synchronized void markCompleted(boolean completed) {
        this.completed = completed;
    }
}

public Worker implements Runnable {

    .
    .
    private WorkStatus workStatus;

    public Worker(int target, int start, int end, WorkStatus workStatus) {
       .
       .
       this.workStatus = workStatus;
    }

    @Override
    public void run() {
       .
       while(!workStatus.isCompleted() && target!=current) {
           .

       }

       if(target==current) {
           workStatus.markCompleted(true);
           .
       }
    }
}

确保将相同的WorkStatus实例传递给所有Worker实例。

创建一个循环以启动线程并将其添加到列表中,找到答案后,您可以遍历该列表以停止其他线程。 如果使用线程池,则可以使用ThreadPoolExecutor.shutdownNow()停止池中的所有其余线程。

停止执行线程的最可靠方法是使用中断并自行实现中断处理。 您可以使用Thread.interrupt()更改Thread.interrupt()的中断状态,并使用Thread.currentThread().isInterrupted()检查线程是否被中断。
在您的情况下,代码可能如下所示:

import java.util.Random;

class Worker extends Thread {
    int target, start, current, end;

public Worker(final int target, final int start, final int end) {
    super();
    this.target = target;
    this.start = start;
    this.end = end;
}

@Override
public void run() {
    current = start;
    while (target != current && !Thread.currentThread().isInterrupted()) {
        System.out.println("Not found  target at " + current);
        current++;
        if (current == end) {
            break;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            break;
        }
    }
    if (target == current) {
        Thread.currentThread().interrupt();
        System.out.println(target + " found");
    }
  }
}

Worker线程将搜索给定的编号,并反复检查该线程是否被中断。 如果线程被中断,则意味着另一个线程找到了该号码。 如果线程找到了要查找的编号,则调用Thread.currentThread().interrupt()向主方法发出已找到该编号的信号,并终止其他工作线程。
主要方法如下所示:

public static void main(final String[] args) {
    Random r = new Random(100);
    int target = r.nextInt(100);
    System.out.println("trying to search " + target);

    Worker w1 = new Worker(target, 1, 30);
    Worker w2 = new Worker(target, 30, 60);
    Worker w3 = new Worker(target, 60, 90);
    Worker w4 = new Worker(target, 90, 100);
    w1.start();
    w2.start();
    w3.start();
    w4.start();

    while (true) {
        if (w1.isInterrupted() || w2.isInterrupted() || w3.isInterrupted() || w4.isInterrupted()) {
            w1.interrupt();
            w2.interrupt();
            w3.interrupt();
            w4.interrupt();
            break;
        } else if (!w1.isAlive() && !w2.isAlive() && !w3.isAlive() && !w4.isAlive()) {
            System.out.println("Invalid search number.");
            break;
        }
    }
}  

在main方法中,我们反复检查线程之一是否被中断。 如果是,则中断其他线程并结束执行。 if子句if (!w1.isAlive() && !w2.isAlive() && !w3.isAlive() && !w4.isAlive())的另一部分是安全检查,如果用户给出了一个线程数不要寻找。 如果所有线程均已完成执行,但未找到编号,则结束程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM