1.为什么要使用多线程
为了充分利用多处理器核心;获得更快的响应速度。
2.创建线程
继承Thread类或者实现Runnable接口,启动线程使用Thread类的start方法,start方法只能调用一次,调用第二次的时候抛出java.lang.IllegalThreadStateException异常。
3.取消线程
3.1 不安全的取消线程
只使用一个取消标志位,如下:
public class TestThread {
private class MyThread implements Runnable{
//使用标志位来取消线程
private volatile boolean on = true;
private long i = 0;
@Override
public void run() {
while (on){
i ++;
// sleep,wait
}
System.out.println("thread end:" + i);
}
private void cancel(){
on = false;
}
}
这样的话如果线程中有阻塞操作的话(例如:Thread.sleep()),就不会被取消的。
stop(),suspend(),resume()是过期的api,使用会导致很大的副作用,造成死锁和数据不一致。
stop(): 立即强制关闭线程,此时如果线程中在进行数据操作,没有处理完数据,会造成数据不一致;
suspend(): 挂起线程,不会释放当前线程持有的锁,会造成死锁。
3.2 安全的取消线程
使用线程的中断:
3.2.1 interrupt() 中断线程,本质是将线程的中断标志位设置为true,其他线程向需要中断的线程打个招呼,是否真正进行中断由线程自己决定。
3.2.2
isInterrupted()
线程检查自己的中断标志位
3.2.3
静态方法
Thread.interrupted()
将中断标志位复位为
false
由上面可知,java中没有抢占式的任务,只有协作式的任务。
3.2.4 为何要用中断 因为线程处于阻塞的时候(rsleep,wait) ,
是不会理会我们自己设置的取消标志位的,但是这些阻塞方法都会检查线程的中断标志位。
安全的取消线程的示例:
public class TestThread {
private class MyThread implements Runnable{
//使用标志位来取消线程
private volatile boolean on = true;
private long i = 0;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()){
i ++;
try {
//抛出中断异常的阻塞方法,抛出中断异常后,中断标志位改成false
Thread.sleep(100L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();//重置下
}
//do my homework
}
//清理工作,结束线程
System.out.println("thread end:" + i);
}
private void cancel(){
on = false;
Thread.currentThread().interrupt();
}
}
}
死锁的状态下,是不会理会中断的。