我有以下代码
package threads;
import java.util.ArrayList;
import java.util.List;
public class Threads extends Thread implements Runnable {
private final List<Thread> threadList = new ArrayList<>();
private String f, l;
private Thread greetings1, greetings;
public static void main(String[] args) {
String[] elements = { "Tim", "Fred", "Jeff", "Scott" };
Threads t = new Threads();
for (String e : elements) {
t.threadL(e);
t.threadR(e);
}
for (int index = 0; index < t.threadList.size(); index++) {
// blank at the moment
}
}
public void threadR(String f) {
greetings = new Thread(f);
Thread greetingsFromFred = new Thread(greetings) {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
try {
System.out.println("Main Thread: " + i + " " + f);
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
};
greetingsFromFred.start();
}
public List<Thread> threadL(String l) {
greetings1 = new Thread(this);
this.l = l;
greetings1.start();
threadList.add(greetings1);
return (threadList);
}
@Override
public void run() {
greetings.interrupt(); // interrupt greetings thread here <-------
System.out.println("Greetings from " + l + "! threadL");
}
}
当threadL运行时,我想中断threadR的运行,从而导致
System.out.println("Main thread interrupted.");
从threadR打印
我在我的代码中突出显示了应该发生中断的事件
greetings.interrupt(); //interrupt greetings thread here <-------
为什么中断不能像现在这样工作?
答案 0 :(得分:3)
你的程序是一个迷宫般的线程对象。让我们尝试从main
开始关注它。
在main
中,您可以创建t
类型的对象Threads
。这意味着它是Thread
和Runnable
。
然后,对于每个字符串,您使用该字符串作为参数运行t
&#39; threadL
和threadR
。
main
中没有任何地方您实际开始t
,甚至直接运行run
方法。
然后,在threadR
中,您创建一个新的空Thread
并将其分配给greetings
。
然后,您将新的空Thread
(问候语)用作Runnable
,并将其传递给同时拥有Thread
方法的新run
对象覆盖。这是徒劳的。在任何情况下,greetingsFromFred
都会启动,并将运行循环。但是greetings
仍然包含与Thread
主题无关的空greetingsFromFred
。
在threadL
中,您创建了另一个Thread
,您将当前Thread
(t
中的main
)作为其可运行对象传递到该greetings
。然后你终于开始了。它将尝试中断Runnable
中的线程,但正如我们所说,这是一个从未启动的非活动空线程。
你的结构应该比那复杂得多。尽可能使用Threads
个对象来处理应该执行的事情。因此,Runnable
本身应该是threadR
,public void threadR(String f) {
Runnable greetingsFromFred = new Runnable() {
@Override
public void run() {
for (int i = 1; i < 5; i++) {
try {
System.out.println("Main Thread: " + i + " " + f);
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("Main thread interrupted.");
}
System.out.println("Main thread exiting.");
}
}
};
greetings = new Thread(greetingsFromFred, f);
greetings.start();
}
应该固定为这样的内容:
greetings
这样,Thread
将是Runnable
,它将运行您在f
中创建的循环,并且名称为{{ 1}}。
但请注意:由于您实际上没有在catch
子句中停止循环,因此当线程中断时您不会退出循环,并且您可能已经&#34;退出&#34;消息打印不止一次,具体取决于中断何时到达循环。
答案 1 :(得分:0)
您需要中断greetingsFromFred
。这是正在启动并实际运行的线程。线程greetings
永远不会运行。是仅作为runnable传递给其他线程。你为什么甚至在一个线程的构造函数中传递一些其他线程?整个设计非常腥。我认为你对线程/ runnable以及何时以及如何使用它感到困惑。
答案 2 :(得分:0)
您要中断的主题称为greetingsFromFred
而非greetings
,因此只要您greetingsFromFred
可见,此更改就会有效。
greetingsFromFred.interrupt(); //interrupt greetings thread here <-------
答案 3 :(得分:0)
正如其他人所指出的,这里有几个问题。
您的班级Threads
有一个run()
方法,可以中断分配给greetings
的任何线程,但R
和L
都不会继承run()
} 方法。 R
扩展Thread
并覆盖run()
,而L
只是扩展Thread
而不会覆盖。这种结构毫无意义。
鉴于此,run()
似乎应该覆盖此L
方法。
如果您实现这一目标,则Threads
无需覆盖Thread
或实施Runnable
。您可以完全取消,并R
和L
各自覆盖Thread
(使用Thread(String)
构造函数)。
public class Threads {
...
public List<Thread> threadL(String l) {
greetings1 = new Thread(l) {
@Override
public void run() {
greetings.interrupt(); // interrupt greetings thread here <-------
System.out.println("Greetings from " + l + "! threadL");
}
...
}
}
现在threadR()
创建并启动一个将被中断的新Thread
,threadL()
创建并启动一个将会中断的新Thread
,并Threads
仅存在main()
方法以及threadR()
和threadL()
中线程的创建/启动。清洁器。
正如其他人所指出的那样,你有这个不必要的变量greetingsFromFred
,这只会使问题复杂化。您为greetingsFromFred
所做的一切都应该代替greetings
(构造函数除外)。
public void threadR(String f) {
greetings = new Thread(f) {
@Override
public void run() {
...
}
greetings.start();
}
greetings
这是IMO中最微妙的部分。您正在使用静态变量greetings
来保存当前Thread
应该中断的当前R
对象L
。但是这两个线程之间没有协调。我们没有理由相信每个L
会在R
中看到唯一的greetings
。那是非常糟糕的事情。您需要做的是让greetings
volatile
,然后让R
等到greetings
为空,然后再分配它,让L
等到greetings
在中断它之前不是null。
private volatile Thread greetings;
...
public void threadR(String f) {
while (greetings != null);
greetings = new Thread(f) {
...
public void threadL(String l) {
Thread greetings1 = new Thread(l) {
@Override
public void run() {
while (greetings == null);
...
请注意while(...);
的使用。尾随分号是一个空的陈述。这个结构只是说要检查条件,直到它为假,然后继续。由于R
永远不会继续进行,直到它有null
然后设置它,并且L
永远不会继续进行,直到它有non-null
然后使其为空,它们将始终保持同步