当其中一个线程完成时停止所有线程

时间:2016-12-30 23:42:09

标签: java multithreading

目标是创建搜索方法,该方法返回首先在所有搜索线程中找到的指针的索引。当其中一个完成后,我需要停止所有线程。

逻辑是:有4个线程。第一个线程检查干草堆的第一个%25,第二个线程检查干草堆的%25-%50,依此类推。

我应该在其中一个人打印文本时立即停止,但我总是得到4个输出,因为所有4个人都在大海捞针中找到针。但是,我只想要一个输出。

示例输出:(下面的索引)

I found, it is: 622
I found, it is: 4072
I found, it is: 7519
I found, it is: 7264

这是SearcherThreat类的扩展线程

public class SearcherThread extends Thread {

// PROPERTIES
private int needle;
private int[] haystack;
private int start, end;

// CONSTRUCTOR
public SearcherThread(int needle, int[] haystack, int start, int end) {
    this.needle = needle;
    this.haystack = haystack;
    this.start = start;
    this.end = end;
}

@Override
public void run() {
    for (int i = start; i < end && !isInterrupted(); ++i) {
        if (haystack[i] == needle) {
            System.out.println("I found, it is: " + i);
            for (SearcherThread searcher : InterruptTest.searchers) {
                searcher.interrupt();
            }

        }
    }
}
}

这是包含main和threads

的类
import java.util.ArrayList;
public class InterruptTest {

public static ArrayList<SearcherThread> searchers = new ArrayList<SearcherThread>();

public static void main(String[] args) throws InterruptedException {

    int itemCount = 10000;
    int[] haystack = new int[itemCount];
    int domainSize = 1000;
    for (int i = 0; i < itemCount; ++i)
        haystack[i] = (int) (Math.random() * domainSize);
    int needle = 10;

    int numThreads = 4;
    int numItemsPerThread = haystack.length / numThreads;
    int extraItems = haystack.length - numItemsPerThread * numThreads;
    for (int i = 0, start = 0; i < numThreads; ++i) {
        int numItems = (i < extraItems) ? (numItemsPerThread + 1) : numItemsPerThread;
        searchers.add(new SearcherThread(needle, haystack, start, start + numItems));
        start += numItems;
    }

    for (SearcherThread searcher : searchers)
        searcher.start();
}
}

2 个答案:

答案 0 :(得分:4)

我得到了这个输出:

interrupt()

正如您所看到的,完成的线程数从一次运行到下一次不等。

我们这里有一场比赛。可能发生的是一个线程在启动之前完成并中断其他线程 。所以他们没有看到中断。 javadoc说:

  

&#34;中断非活动的线程无需任何效果。&#34;

另一种可能性是中断传播速度不够快。请注意,javadoc并未表示中断线程可立即看到(every? true? []) => true (every? false? []) => true (every? odd? []) => true

我无法想到一个解决方案,它不能否定多线程的好处。另一方面,在现实世界的用例中:

  • 您应该使用线程池...因为线程创建相对昂贵。
  • 线程应该做更多工作。

如果您测量的是当前测试中的实际加速比,则可能

总之,在更现实的测试中,您应该看到中断大部分时间都在 。这应该足够好了。 (无论何时,线程都不能足够快地中断以阻止它们找到次要结果。)

答案 1 :(得分:0)

这是死灵,但这可以帮助其他人。您可以使用Java内置的Executors。对于Java 8,它具有

  1. newCachedThreadPool()
  2. newFixedThreadPool(int nThreads)
  3. newSingleThreadExecutor()

这是一个示例,说明如何编写您的课程。我正在使用newFixedThreadPool(int nThreads)来匹配您在代码中所做的事情

import java.util.concurrent.Callable;

public class SearcherThread implements Callable<Object> {

// PROPERTIES
    private int needle;
    private int[] haystack;
    private int start, end;

// CONSTRUCTOR
    public SearcherThread(int needle, int[] haystack, int start, int end) {
        this.needle = needle;
        this.haystack = haystack;
        this.start = start;
        this.end = end;
    }


    @Override
    public Object call() throws Exception {
        for (int i = start; i < end ; ++i) {
            if (haystack[i] == needle) {
                return i;


            }
        }
        Thread.sleep(5000);
        return null;
    }
}

和Test类

import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class InterruptTest {

    public static ArrayList<SearcherThread> searchers = new ArrayList<SearcherThread>();

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        int itemCount = 10000;
        int[] haystack = new int[itemCount];
        int domainSize = 1000;
        for (int i = 0; i < itemCount; ++i)
            haystack[i] = (int) (Math.random() * domainSize);
        int needle = 10;

        int numThreads = 4;
        int numItemsPerThread = haystack.length / numThreads;
        int extraItems = haystack.length - numItemsPerThread * numThreads;
        for (int i = 0, start = 0; i < numThreads; ++i) {
            int numItems = (i < extraItems) ? (numItemsPerThread + 1) : numItemsPerThread;
            searchers.add(new SearcherThread(needle, haystack, start, start + numItems));
            start += numItems;
        }
        //Preferred to use Executors.newWorkStealingPool() instead
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);
        executor.shutdown();//shutdown when done
        Object result = executor.invokeAny(searchers);//<------- right here lookie
        System.out.println("I found, it is: "+result);
    }
}

ExecutorService.invokeAny(List )将运行所有可调用线程并获取第一个完成线程的值。