1. 中断线程
有时线程需要执行长时间的任务,比如下载一个1GB的大文件,但或许由于网速过慢,导致用户点击取消下载,这时就需要中断这个线程。
在Java中,只需要在其他线程中对目标线程调用interrupt()
方法,然后目标线程反复检测自身状态是否为interrupt
状态,如果是,就立即结束。
示例代码:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(1);
t.interrupt();
t.join();
System.out.println("end");
}
}
class MyThread extends Thread {
public void run() {
int n = 0;
while (!isInterrupted()) {
n++;
System.out.println(n + " hello!");
}
}
}
上述代码中,在main()
函数中调用t.interrupt()
仅仅是给目标线程t
发了一个中断线程的信号,还需要目标线程t
反复检测自身的interrupt
状态。
同时,还发现在main()
函数中抛出了一个InterruptedException
异常,该异常直接继承至Exception
,为Checked Exception
,所以必须捕获或者抛出。
当一个线程调用了join()
等待其他线程结束时,被另一个线程调用了interrupt()
方法,就会立即抛出InterruptedException
异常。
示例代码:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new MyThread();
t.start();
Thread.sleep(1000);
t.interrupt(); // 中断t线程
t.join(); // 等待t线程结束
System.out.println("end");
}
}
class MyThread extends Thread {
public void run() {
Thread hello = new HelloThread();
hello.start(); // 启动hello线程
try {
hello.join(); // 等待hello线程结束
} catch (InterruptedException e) {
System.out.println("interrupted!");
}
hello.interrupt();
}
}
class HelloThread extends Thread {
public void run() {
int n = 0;
while (!isInterrupted()) {
n++;
System.out.println(n + " hello!");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
break;
}
}
}
}
上述代码中,MyThread
中调用hello.join()
方法后,会等待hello
线程结束。但此时main()
中对MyThread
线程调用了t.interrupt()
方法,使得hello.join()
立即抛出InterruptedException
异常。
此外,线程间共享变量需要加上volatile
关键字。
2. 守护线程
当所有线程都结束时,进程才结束。
当有一些线程就是无限循环的,比如通过定时器线程来更新界面上的时间,如果这个线程不结束,JVM进程就无法结束。
通常这类线程被设置成守护线程,意思是指为其他线程服务的线程,当所有非守护线程都结束时,进程就会自动结束。
在Java中只需要调用start()
方法前,调用setDaemon(true)
即可把该线程设置为守护线程。
示例代码:
Thread t = new MyThread();
t.setDaemon(true);
t.start()