如何在其中一个工作完成后停止工作线程?

时间:2016-03-30 06:04:40

标签: java multithreading

我正在进行简单的模拟,就像破解哈希一样,我希望所有其他工作人员在其中一个人找到结果时停止?除了停止之外还有其他方法,因为已弃用吗?

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();
}

}

4 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:1)

使用通用数据结构存储标志并将数据结构的同一实例传递给每个工作线程。找到目标的工作人员将在退出之前设置标志。检查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实例。

答案 2 :(得分:0)

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

答案 3 :(得分:0)

停止执行线程的最可靠方法是使用中断并自己实现中断处理。您可以使用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())的另一部分是安全检查,如果用户给出了线程不寻找的数字。如果所有线程都已完成执行并且未找到该号码,则结束该程序。