我正在阅读此post,并且建议从另一个线程中断一个线程
“”“如果正确实施,以下是一些应该有效的方法。
您可以让threads
定期检查一些常见的标志变量(例如将其命名为stopNow),并安排两个线程在完成后设置它。 (标志变量需要是易失性的......或者是正确同步的。)
您可以让threads
定期调用Thread.isInterrupted()方法来查看它是否已被中断。然后每个线程在完成时需要在另一个线程上调用Thread.interrupt()。“”“
我不明白第二种方法如何使用Thread.isInterrupted()
。
也就是说,Thread-1
Thread.interrupt()
如何调用Thread-2
。
考虑这个例子,在主要方法中,我开始两个threads
t1
和t2
。我希望t1
在达到某个条件后停止t2
。我怎么能实现这个目标呢?
class Thread1 extends Thread {
public void run(){
while (!isDone){
// do something
}
} //now interrupt Thread-2
}
class Thread2 extends Thread {
public void run(){
try {
while(!Thread.isInterupted()){
//do something;
}
catch (InterruptedExecption e){
//do something
}
}
}
public class test {
public static void main(String[] args){
try {
Thread1 t1 = new Thread1();
Thread2 t2 = new Thread2();
t1.start();
t2.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:2)
public class test {
private static boolean someCondition = true;
public static void main(String[]args){
Thread t2 = new Thread(new someOtherClass("Hello World"));
Thread t1 = new Thread(new someClass(t2));
t2.start();
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static class someClass implements Runnable{
Thread stop;
public someClass(Thread toStop){
stop = toStop;
}
public void run(){
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(someCondition && !stop.isInterrupted()){
stop.interrupt();
}
}
}
}
static class someOtherClass implements Runnable{
String messageToPrint;
public someOtherClass(String s){
messageToPrint = s;
}
public void run(){
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(messageToPrint);
}
}
}
}
答案 1 :(得分:2)
这样做的背景是你试图使用线程中断来实现你的方案。
为了实现这一点,t1
对象需要引用t2
线程对象,然后只需调用t2.interrupt()
。
t1
可以通过多种方式获取对t2
的引用。
t2
名称的线程。答案 2 :(得分:0)
您可以考虑使用Future
接口。它提供了cancel()
方法。
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html
答案 3 :(得分:0)
中断玩耍会让你的生活变得不必要。除了您的代码必须知道线程这一事实外,中断不会提供有关中断原因的任何上下文信息。
如果您的代码共享的条件可能由不同的线程执行,只需将该条件封装到对象中并共享该对象:
public class Test {
public static void main(String[] args) {
Condition c=new Condition();
new Thread(new Setter(c)).start();
new Thread(new Getter(c, "getter 1")).start();
// you can simply extend it to more than one getter:
new Thread(new Getter(c, "getter 2")).start();
}
}
class Getter implements Runnable {
final Condition condition;
final String name;
Getter(Condition c, String n) { condition=c; name=n; }
public void run() {
while(!condition.isSatisfied()) {
System.out.println(name+" doing something else");
try { Thread.sleep(300); } catch(InterruptedException ex){}
}
System.out.println(name+" exiting");
}
}
class Setter implements Runnable {
final Condition condition;
Setter(Condition c) { condition=c; }
public void run() {
System.out.println("setter: doing my work");
try { Thread.sleep(3000); }
catch(InterruptedException ex){}
System.out.println("setting condition to satisfied");
condition.setSatisfied();
}
}
class Condition {
private volatile boolean satisfied;
public void setSatisfied() {
satisfied=true;
}
public boolean isSatisfied() {
return satisfied;
}
}
这种封装的一大优势是它易于扩展。假设您希望允许线程等待条件而不是轮询它。使用上面的代码很容易:
class WaitableCondition extends Condition {
public synchronized boolean await() {
try {
while(!super.isSatisfied()) wait();
return true;
} catch(InterruptedException ex){ return false; }
}
public synchronized void setSatisfied() {
if(!isSatisfied()) {
super.setSatisfied();
notifyAll();
}
}
}
class Waiter implements Runnable {
final WaitableCondition condition;
final String name;
Waiter(WaitableCondition c, String n) { condition=c; name=n; }
public void run() {
System.out.println(name+": waiting for condition");
boolean b=condition.await();
System.out.println(name+": "+(b? "condition satisfied": "interrupted"));
}
}
在不更改其他类的情况下,您现在可以扩展测试用例:
public class Test {
public static void main(String[] args) {
WaitableCondition c=new WaitableCondition();
new Thread(new Setter(c)).start();
new Thread(new Getter(c, "getter 1")).start();
// you can simply extend it to more than one getter:
new Thread(new Getter(c, "getter 2")).start();
// and you can have waiters
new Thread(new Waiter(c, "waiter 1")).start();
new Thread(new Waiter(c, "waiter 2")).start();
}
}