1、终止线程
1. Thread.stop()
Thread 类的 stop()方法,已废弃。原因:在结束线程时,会直接终止线程,并且会立即释放这个线程所持有的锁。如果写线程写入数据写到一半,强行终止,可能造成对象被写坏。
2. 使用退出标记
3. Thread.interrupt()
2、线程中断
线程中断并不会使线程立即退出,指示给线程发一个通知,告诉线程有人希望你退出。
public void Thread.interript() // 通知目标线程中断,并设置中断标志位
public boolean Thread.isInterrupt() // 判断是否被中断
public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态标志
//由于中断会抛出异常,但是此时,它会清除中断标志位
public static native sleep(long millis) throws InterruptedException
3、等待(wait)和通知(notify)
public final void wait() throws InterruptedException
public final native void notify()
这两个方法是在Object类中。他们必须包含在对应的 synchronized 语句中,都需要先获得目标对象的一个监视器。
Object.wait() 和 Thread.sleep() 区别:
- 都可以让线程等待若干时间。
- wait 可以被唤醒,会释放目标对象的锁,进入对象的等待池(wait pool),调用notify()方法进入等锁池。 sleep 不会释放任何资源,等休眠时间结束后会自动恢复,线程回到就绪状态。
- sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。如果不捕获这个异常,线程就会异常终止
4、等待线程结束(join)和谦让(yield)
1. join:线程间的等待
public final void join() throws InterruptedException //无线等待,直到目标线程执行完毕
public final synchrozied void join(long millis) throws InterruptedException //最大等待
// join核心代码,本质上是调用wait()在当前线程对象实例上
while(isAlive) {
wait(0);
}
对于join,它让调用线程在当前线程对象上进行等待。当线程执行完后,被等待的线程会在退出前调用 notifyAll() 通知所有的等待线程继续执行。所以需要注意的是不要在Thread对象实例上使用类似wait() 或 notify()等方法,以免相互影响。
2. yield:线程间的谦让
yield的作用是放弃当前CPU的资源,将它让给其他线程区占用CPU的执行时间。
// 使当前线程让出CPU,进入就绪状态
public static native void yield();
线程的sleep()方法和yield()方法区别
- sleep()方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield()方法只会给相同优先级或更高优先级的线程以运行的机会;
- 线程执行sleep()方法后转入阻塞(blocked)状态,而执行yield()方法后转入就绪(ready)状态;
- sleep()方法声明抛出InterruptedException,而yield()方法没有声明任何异常;
- sleep()方法比yield()方法(跟操作系统CPU调度相关)具有更好的可移植性。
5、挂起(suspend)和继续执行(resume)
这两个方法都已被标为废弃,不推荐使用。
原因:suspend() 在导致线程暂停执行的同时,并不会释放任何资源。其他线程想要获取它占用的锁时,就无法获取到,导致无法正常运行。直到对应的线程上执行了resume()。
6、驻守后台:守护线程(Daemon)
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
守护线程是一种特殊的线程,是系统的守护者,在后台默默完成一些系统的服务,比如垃圾回收、JIT线程等。
与之对应的就是用户线程,就是系统的工作线程。如果用户线程全部结束,那么守护线程要守护的对象已经不存在了,那整个应用就自然应该结束。当一个Java应用内,只有守护线程时,虚拟机就会自动退出。
注意:从isAlive() 判断看出,setDaemon()必须在start()之前调用。
7、线程优先级
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
Java默认使用1到10表示线程优先级。