我有一个简单的例子。我想要做的是通过将它分成2个线程来搜索arraylist。这是我的主要代码;
class LinearSearch {
public static void main(String args[]) {
int list[] = new int[1000];
for (int j = 0; j < list.length; j++)
list[j] = (int) (Math.random() * 1000);
for (int y : list)
System.out.print(y + " ");
System.out.println();
System.out.print("Enter number to search for: ");
Scanner in = new Scanner(System.in);
int x = in.nextInt();
Searcher t = new Searcher(list, 0, 500, x);
Searcher t1 = new Searcher(list, 500, 1000, x);
t.start();
t1.start();
try {
t.join();
t1.join();
} catch (InterruptedException e) {
}
boolean found = t.getResult() || t1.getResult();
System.out.println("Found = " + found);
}
}
这是Searcher课程;
class Searcher extends Thread {
private int f[];
private int lb, ub;
private int x;
private boolean found;
Searcher(int f1[], int a, int b, int x) {
f = f1;
lb = a;
ub = b;
this.x = x;
}
public void run() {
int k = lb;
found = false;
while (k < ub && !found) {
if (f[k] == x){
found = true;
this.interrupt();
}
k++;
}
}
boolean getResult() {
return found;
}
}
我将数组除以2,让线程完成它们的工作。问题是,即使一个线程找到该号码,另一个线程仍然继续其搜索。当我在网上寻找答案时,我找到了Threads的中断方法。 如果我在我的Searcher Thread类中使用中断方法,它将停止两个线程或它将停止找到该数字的实例?
顺便说一句,如果您有其他问题解决方案,除了打断,请告诉我
提前致谢
答案 0 :(得分:1)
调用interrupt()
显然不是要走的路,因为你需要中断所有相当费力的线程,而且你不能同时中断所有线程,你应该共享一个{{ 1}}表示状态AtomicBoolean
,因为found
上的任何修改都将立即被所有线程看到,这样所有线程将在AtomicBoolean
返回get()
后停止迭代。
这样的事情:
true
如果您使用class Searcher extends Thread {
...
// Used to know if the current thread was the one who found the result
private boolean hasFound;
private final AtomicBoolean found;
Searcher(AtomicBoolean found, int f1[], int a, int b, int x) {
this.found = found;
...
}
public void run() {
int k = lb;
while (!found.get() && k < ub) {
if (f[k] == x){
found.set(hasFound = true);
// Use a break instead to exit from the loop
break;
}
k++;
}
}
boolean getResult() {
return hasFound;
}
}
,可以使用Java 8
作为下一步尝试实现的目标:
Stream API
答案 1 :(得分:1)
中断线程并不能做任何事情:
while (k < ub && !found) {
if (f[k] == x){
found = true;
this.interrupt();
}
k++;
}
所有这一切都是在线程上设置一个标志来说&#34;某些事情打断了我&#34; - 你不会在任何地方检查那个标志,所以没有任何事情发生。
您可以检查while循环防护中的标志:
while (k < ub && !found && !Thread.interrupted())
(其中interrupted
将清除标记的状态(如果已设置);您还可以使用Thread.isInterrupted
检查状态而不清除它。)
但这里的问题是你真的不需要打断当前线程 - 你已经知道你已经通过{{1}在这个帖子中找到了一些东西标志。如果您要打断任何线程,那么其他线程需要被中断。所以你需要引用found
类中的另一个线程,以便你可以中断它。
但是,你根本不需要使用中断:如果你给两个线程都相同Searcher
,他们可以检查一下:
AtomicBoolean
使用while (k < ub && !found.get()) {
if (f[k] == x) {
found.set(true);
}
k++;
}
的另一个好处是除了其中一个搜索者之外什么都不能停止搜索 - 你可以通过AtomicBoolean
类的静态方法获得对任何线程的引用,允许JVM中任何地方的任何代码都会中断搜索。
通过使用Thread
,只有这两个搜索者实例能够阻止另一个搜索器实例,因为AtomicBoolean
无法从外部获取(好吧,也许它可能是超级邪恶的装置)。
但是,正如Brian Goetz指出的那样,你也可以使用AtomicBoolean
。
答案 2 :(得分:1)
将您在LinearSearch类中创建的线程存储在一个数组中,并使它们可供Searcher类访问。一旦你的found被设置为true,就杀掉所有的线程。另外,为Searcher类中的线程提供唯一的ID作为ID。
class Searcher extends Thread {
private int f[];
private int lb, ub;
private int x;
private boolean found;
private int id;
Searcher(int f1[], int a, int b, int x, int id) {
f = f1;
lb = a;
ub = b;
this.x = x;
this.id = id;
}
public void run() {
int k = lb;
found = false;
while (k < ub && !found) {
if (f[k] == x){
found = true;
//this.interrupt();
killAllThreads();
}
k++;
}
}
boolean getResult() {
return found;
}
//assuming your class has access to allThreads array somehow. You will have to decide the best way to keep this variable accessible to this class. Handle null pointer exceptions in your run method
private void killAllThreads(){
for(int i=0; i<allThreads.length; i++){
if(allThreads[i].id != this.id){
if(allThreads[i] != null)
allThreads[i] = null;
}
}
}
}
但是,请参考here如何安全地杀死线程。