I'm trying to search for the first occurrence of number 0 in an array by using a thread for each row and then interrupting all threads if 1 thread found the occurrence. I read multiple questions and answers but couldn't find a simple way and I tried using a variable "found" to not run the other threads. However, it's not working and I couldn't figure out the problem. I mainly wanted to use interrupt() instead of using a variable. Any help would be appreciated.
Search 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;
}
}
}
Main 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();
}
}
}
Output:
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
CodePudding user response:
Your found
variable is not volatile
, which means that after a certain thread finds it, and this thread set found
to true
, and other threads cannot immediately perceive it, and they will continue to find.
But even if you set it to volatile
, it is not enough, because multiple threads may find it at the same time.
So, if you want to strictly control only one thread will print Found at:...
, you need to use a lock
instead of 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;
}
}
}
}
CodePudding user response:
First of all, using the volatile
keyword is necessary since you are working with variables that are shared and used by different threads.
I recommend passing only the row to the thread and not the whole array. That would not be needed. And lastly, you could use a flag to check whether an occurrence of 0 was found or not. If it is found, stop the threads.
The below example fulfills your needs.
// 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...
}
}