强制代码使用 while 循环等待条件需要 thread.sleep()



我创建了一个程序,将线性搜索(搜索-1(划分为4个单独的线程。

public class main {
static boolean found = false;
public static void main(String[] args) {
// TODO Auto-generated method stub
int threadCount = 4; //amount of threads to use
Random rand = new Random();
Searcher[] s_arr = new Searcher[threadCount]; //array of threads

int[] arr = new int[10000]; //array to search through
for (int i = 0; i < arr.length; i++) //randomizing #'s in array
arr[i] = (int) (rand.nextFloat() * 1000);
int randIndex = rand.nextInt(arr.length); //choose random index
arr[randIndex] = -1; //set random index to = -1
for (int i = 0; i < threadCount; i++) { //
s_arr[i] = new Searcher(Arrays.copyOfRange(arr, i * (arr.length/threadCount), (i+1) * (arr.length/threadCount)), 
(int) (i), i); //assign subarray for this thread to search through
System.out.println(s_arr[i].wait);
s_arr[i].start(); 
}

//CODE IN QUESTION HERE ----------------------------
//while (!found) ;
while (!found) //wait until value is found
{
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//-----------------------------------------------------------


System.out.println("found!");
for (int i = 0; i < threadCount; i++) {
try {
s_arr[i].join(); //wait for the threads in order before continuing
System.out.println("Thread ["+i+"] completed");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("All threads stopped, program complete.");
}
}
public class Searcher extends Thread {
int[] arr;
int wait;
int index;
public Searcher(int[] arr, int wait, int i) {
this.arr = arr;
this.wait = wait;
this.index = i;
}
@Override
public void run() {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == -1) {
System.out.println("["+index+"] -1 Found at index: "+i);
main.found = true;
break;
}
if (main.found) break;
//purposely slow down this thread
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("["+index+"] has stopped");
}
}

我已经标记了有问题的代码,在使用第一个(注释掉的(while 循环时,程序不会超出该点,但是如果我切换并使用它下方的另一个 while 循环(强制它等待每个迭代器 1 毫秒的循环(,程序工作正常。

为什么会这样,是否有更有效/更实用的方法来完成这项任务?

空循环语句的条件下重复读取非易失性字段可能会导致无限循环,因为编译器优化可能会将此字段访问移出循环。

来源:help.semmle.com

如果你用volatile static boolean found = false;替换static boolean found = false;,第一个循环会起作用,但我不建议这样做,因为它会浪费你的CPU时间。 您应该考虑使用waitnotify.

static boolean found下面,添加static final Object lock = new Object();并将两个while循环替换为

try {
synchronized (lock) {
// we will wait here until we get notified
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}

同样在main.found = true添加之后

synchronized (main.lock) {
main.lock.notify();
}

最后,您的代码应如下所示

public class main {
static boolean found;
static final Object lock = new Object();
public static void main(String[] args) {
// TODO Auto-generated method stub
int threadCount = 4; //amount of threads to use
Random rand = new Random();
Searcher[] s_arr = new Searcher[threadCount]; //array of threads

int[] arr = new int[10000]; //array to search through
for (int i = 0; i < arr.length; i++) //randomizing #'s in array
arr[i] = (int) (rand.nextFloat() * 1000);
int randIndex = rand.nextInt(arr.length); //choose random index
arr[randIndex] = -1; //set random index to = -1
for (int i = 0; i < threadCount; i++) { //
s_arr[i] = new Searcher(Arrays.copyOfRange(arr, i * (arr.length/threadCount), (i+1) * (arr.length/threadCount)),
(int) (i), i); //assign subarray for this thread to search through
System.out.println(s_arr[i].wait);
s_arr[i].start();
}
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("found!");
for (int i = 0; i < threadCount; i++) {
try {
s_arr[i].join(); //wait for the threads in order before continuing
System.out.println("Thread ["+i+"] completed");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("All threads stopped, program complete.");
}
}
class Searcher extends Thread {
int[] arr;
int wait;
int index;
public Searcher(int[] arr, int wait, int i) {
this.arr = arr;
this.wait = wait;
this.index = i;
}
@Override
public void run() {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == -1) {
System.out.println("["+index+"] -1 Found at index: "+i);
main.found = true;
synchronized (main.lock) {
main.lock.notify();
}
break;
}
if (main.found) break;
//purposely slow down this thread
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("["+index+"] has stopped");
}
}

最新更新