我正在尝试理解线程如何在Java中工作,并且正在研究如何实现可以取消的循环线程。这是代码:
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
@Override
public void run() {
System.out.println("THREAD: started");
try {
while(!isInterrupted()) {
System.out.printf("THREAD: working...\n");
Thread.sleep(100);
}
} catch(InterruptedException e) {
// we're interrupted on Thread.sleep(), ok
// EDIT
interrupt();
} finally {
// we've either finished normally
// or got an InterruptedException on call to Thread.sleep()
// or finished because of isInterrupted() flag
// clean-up and we're done
System.out.println("THREAD: done");
}
}
};
t.start();
Thread.sleep(500);
System.out.println("CALLER: asking to stop");
t.interrupt();
t.join();
System.out.println("CALLER: thread finished");
}
我创建的主题 indended 迟早会中断。所以,我检查了isInterrupted()标志来判断我是否需要继续操作并在我进行某种等待操作(InterruptedException
,sleep
时捕获join
来处理这些情况, wait
)。
我想澄清的事情是:
volatile boolean shouldStop
) 修改
在interrupt()
的catch中添加了对InterruptedException
的调用。
答案 0 :(得分:4)
我回答不是。 3:
基本上问题是:中断异常的目的是什么?它告诉你停止阻止(例如睡觉)并提前返回。
处理InterruptedException有两种方法:
Thread.currentThread.interrupt()
并进行清理工作。通过这种方式,您可以确保线程中的另一个方法开始重新启动简单地吞咽InterruptedException
对于最终终止的中断的目的并不是一个好主意。但是你只被要求打断,所以你还有时间清理。
在这种情况下,这可能是我自己的“过度反应”,但通常这样的代码要复杂得多,你怎么知道,这个Thread中的一些后续代码不会再次调用阻塞方法?
修改强>
否则我认为你所做的很好。但是对我来说有点令人惊讶,因为我从未在他自己的代码中看到任何人实际上这样做。
有趣的文章解释了为什么可以在这里找到:http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html
答案 1 :(得分:2)
Thread.currentThread().interrupt();
答案 2 :(得分:1)
1)根据 Java Concurrency in Practice 一书,你的例子中的方法比使用易失性标志(因为你已经有中断的标志是冗余的)更可取。这是InterruptedExceptions的使用方式。
2)是的
3)只要恢复中断标志状态,就可以吃异常。该例外不代表错误,所以吃掉它不会丢失任何信息,它纯粹是一种转移控制的手段。 (恢复中断标志状态对于你有嵌套控制结构的情况很重要,每个嵌套控制结构都需要通知线程正在取消,对于一个简单的例子,像你的它是好的形式但是如果它缺失它不会伤害任何东西。)< / p>
4)没有
答案 3 :(得分:1)
使用中断很好,但使用它们很好。你必须重新抛出Thread.currentThread().interrupt()
。这是一段显示原因的代码:
public class MyThread extends Thread {
private static boolean correct = true;
@Override
public void run() {
while (true) {
// Do Something 1
for (int i = 0; i < 10; i++) { // combined loop
// Do Something 2
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt(); // reinterrupting
System.out.println("First Catch");
break; // for
}
}
try {
// Do Something 3
System.out.print("before sleep, ");
Thread.sleep(1000);
System.out.print("After sleep, ");
} catch (InterruptedException ex) {
if (correct)
Thread.currentThread().interrupt();
System.out.println("Second catch");
break; // while
}
}
System.out.println("Thread closing");
}
private static void test() throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(2500);
t.interrupt();
t.join();
System.out.println("End of Thread");
}
public static void main(String[] args)
throws InterruptedException {
test();
correct = false; // test "bad" way
test();
}
}
另一件事是,Interruptions
在等待InputStreams
时并不总是有效。然后,您可以使用(对某些人)InterruptedIOException
,但它并不总是有效。要了解这些情况,您可能需要尝试这段代码:
public class Mythread extends Thread {
private InputStream in;
public Mythread(InputStream in) {
this.in = in;
}
@Override
public void interrupt() {
super.interrupt();
try {
in.close(); // Close stream if case interruption didn't work
} catch (IOException e) {}
}
@Override
public void run() {
try {
System.out.println("Before read");
in.read();
System.out.println("After read");
} catch (InterruptedIOException e) { // Interruption correctly handled
Thread.currentThread().interrupt();
System.out.println("Interrupted with InterruptedIOException");
} catch (IOException e) {
if (!isInterrupted()) { // Exception not coming from Interruption
e.printStackTrace();
} else { // Thread interrupted but InterruptedIOException wasn't handled for this stream
System.out.println("Interrupted");
}
}
}
public static void test1() // Test with socket
throws IOException, InterruptedException {
ServerSocket ss = new ServerSocket(4444);
Socket socket = new Socket("localhost", 4444);
Thread t = new Mythread(socket.getInputStream());
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void test2() // Test with PipedOutputStream
throws IOException, InterruptedException {
PipedInputStream in = new PipedInputStream(new PipedOutputStream());
Thread t = new Mythread(in);
t.start();
Thread.sleep(1000);
t.interrupt();
t.join();
}
public static void main(String[] args) throws IOException, InterruptedException {
test1();
test2();
}
}