我创建了一个程序,将线性搜索(搜索 -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 毫秒)程序运行良好。
这是为什么,是否有更有效/实用的方法来完成此任务?
最佳答案
Repeatedly reading a non-volatile field within the condition of an empty loop statement may result in an infinite loop, since a compiler optimization may move this field access out of the loop.
来源:help.semmle.com
如果将 static boolean found = false;
替换为 volatile static boolean found = false;
,第一个循环会起作用,但我不推荐这样做,因为它会浪费你的CPU时间。
您应该考虑使用 wait
和 notify
。
在 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");
}
}
关于java - 使用 while 循环强制代码等待条件需要 thread.sleep(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58252656/