Java-如何为每一行使用线程搜索数组并在找到后停止所有 运行 线程?

Java-How to search an array using a thread for each row and stop all running threads if found?

我正在尝试通过为每一行使用一个线程来搜索数组中数字 0 的第一次出现,然后如果有一个线程发现该事件则中断所有线程。我阅读了多个问题和答案,但找不到简单的方法,我尝试使用变量“找到”而不是 运行 其他线程。但是,它不起作用,我无法找出问题所在。我主要想使用 interrupt() 而不是使用变量。任何帮助将不胜感激。

搜索class

public class Search extends Thread {
    int low;
    int high;
    int[][] array; 
    static int id=0;  
    private static boolean found = false;
    private boolean done = false;

    public Search(int[][] array, int low, int high) {
        id++;
        this.array = array;
        this.high = high;
        this.low= low;
    }

    public void run(){

        whileLoop:  while(!found && !done){
            for(int i = low; i < high; i++){
                for(int j = 0; j < array[i].length; j++){
                    if(array[i][j] == 0){
                        System.out.println("Found at: "+i+" "+j + " By thread "+id);
                        found = true;
                        done = true;
                        break whileLoop;
                    }
                }
            }
            done = true;
        }
       
    }
}

主要class

public class Main{
    public static void main(String[] args){
        int[][] array = {{3,0,2,3,0,5},{2,4,0,2,6,5},{4,1,2,4,6,5},{0,2,1,4,0,5},{4,5,6,0,7,1},{9,7,4,1,1,3}}; //6 zeros
        SearchArray searchArray =  new SearchArray();

        searchArray.sArray(array);
    }
}


class SearchArray{

    public void sArray(int[][] array){
        int noThreads = array.length;
        Search[] threads = new Search[noThreads];

        for(int i = 0; i < threads.length; i++){
            threads[i] = new Search(array, i*1 , (i + 1) * 1);
            threads[i].start();
        }
    }
}

输出:

Found at: 0 1 By thread 5
Found at: 3 0 By thread 6
Found at: 1 2 By thread 5
Found at: 4 3 By thread 6

首先,使用 volatile 关键字是必要的,因为您正在处理由不同线程共享和使用的变量。

我建议只将行传递给线程而不是整个数组。那是不需要的。最后,您可以使用标志来检查是否找到了 0。如果找到,则停止线程。

下面的例子可以满足您的需求。

// the volatile keyword is important
public static volatile int[][] array = {{3,0,2,3,0,5},{2,4,0,2,6,5},{4,1,2,4,6,5},{0,2,1,4,0,5},{4,5,6,0,7,1},{9,7,4,1,1,3}}; //6 zeros
public static volatile boolean found = false;

public static void main(String[] args)
{
    for (int i = 0; i < array.length; i++) // Iterate through each row
    {
        int finalI = i;

        Thread th = new Thread() // Create a new thread for each row
        {
            @Override
            public void run()
            {
                for (int j = 0; j < array[finalI].length; j++) // Each thread will iterate through each element
                {
                    if(found) // If the element 0 was found, then break and stop the thread
                    {
                        System.out.println("Another thread found 0, so stopping this thread.");
                        break;
                    }

                    if(array[finalI][j] == 0) // If this is the thread that finds 0, then log and set flag to true
                    {
                        System.out.println(this.getName() + " found 0 at index " + finalI + "," + j);
                        found = true;
                        break;
                    }
                }
            }
        };

        th.start(); // Start each thread...
    }
}

你的found变量不是volatile,意思是某个线程找到后,这个线程把found设置为true,其他线程不能立即感知,他们会继续寻找。

但是即使设置成volatile也不够,因为可能多个线程同时找到

所以,如果你想严格控制只有一个线程会打印Found at:...,你需要使用lock而不是volatile(lock->check->act) :

public void run(){
    for(int j = 0; j < array[low].length; j++){
        if (found) {
            break;
        }
        if(array[low][j] == 0){
            // lock,check,act
            // if found, lock
            // array here can be a lock, since all threads share this array
            synchronized (array) {
                // check
                if (found) {
                    break;
                }
                found = true;
                System.out.println("Found at: "+low+" "+j + " By thread "+id);
                break;
            }
        }
    }
}