线程有五种状态:
创建、就绪、运行、阻塞、结束
创建:当使用new创建新的线程时,处于创建状态
就绪:调用start方法后,线程并不是立即处于运行状态,而是出于就绪态
运行:当线程被分配CPU后,运行run方法后才处于运行状态
阻塞:线程因为某些原因让出CPU使用权,直到重新进入运行态(如调用sleep方
法)
死亡:线程处于死亡状态
- run方法的正常退出或异常退出,线程死亡
- 异常导致线程死亡
线程的常用方法:
sleep():线程休眠
- 指的是让线程暂缓执行一下,等到了预计时间再恢复执行
- 线程休眠会立即交出CPU,让CPU去执行其他任务
- 线程休眠不会释放对象锁。
调用sleep方法会让线程进入阻塞状态:当调用sleep方法后,会出现等待时间超时的情况,因为此时CPU有可能正在执行其他任务,等会儿才能来执行当前线程
yield():线程让步
- 暂停当前正在执行的对象,并执行其他线程
- 会交出CPU,但是不确定交出CPU的时间
- 线程让步不会释放对象锁
- 只能让拥有相同优先级的线程有获取CPU的机会
调用yield()不会让线程进入阻塞状态,此时线程计入就绪态,若线程优先级高于其他的线程,那么这个线程即使执行了 yield() 方法也可能不能起到让出CPU控制权的效果,因为它让出控制权后,进入排队队列,调度机制将从等待运行的线程队列中选出一个等级最高的线程来运行,那么它又很可能被选中来运行。
sleep与yield区别: - sleep()立即交出CPU,yield()不能确定什么时候交出CPU
- 调用sleep(),线程回到阻塞态后回到就绪态
调用yield(),线程回到就绪态 只能让同等优先级的线程有获得CPU的机会
join():等待调用join的线程终止
- 等待该线程终止。会释放对象锁,让线程进入阻塞状态
- 如果在主线程中调用join方法会让主线程休眠,让调用join方法的线程子先执行完毕后再恢复执行主线程,若调用的是有参构造,就等待一定时间后恢复执行主线程
- 实际上调用join()是调用了Object类的wait方法,会释放对象锁
if (millis == 0) {
while (isAlive()) {
wait(0);
}
}
interrupt():线程停止
- 中断一个正处于阻塞状态的线程
isInterrupt():判断当前线程是否被中断
返回值为true,非阻塞状态
返回值为false,阻塞状态
如果线程的当前状态为阻塞状态,那么中断标志位会改为false,若调用wait、sleep、join方法就会抛出中断异常 - 调用interrupt方法,本质只是设置该线程的中断标志,将中断标志位设为true,再根据线程状态(阻塞/非阻塞)决定如何退出线程(是否抛出异常)
class Demo implements Runnable{
boolean flag = true;
@Override
public void run() {
int i = 1;
while (flag){
try {
Thread.sleep(1000);
boolean bool = Thread.currentThread().isInterrupted();
//true:非阻塞 false:阻塞
if (bool){
System.out.println("非阻塞执行操作。。。线程状态"+bool);
break;
}
System.out.println("第"+i+"次执行,线程名称:"+
Thread.currentThread().getName());
i++;
} catch (InterruptedException e) {
boolean bool = Thread.currentThread().isInterrupted();
System.out.println("阻塞状态:"+bool);
e.printStackTrace();
return;
}
}
}
}
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new Demo());
thread.start();
Thread.sleep(3000);
thread.interrupt();
System.out.println("over");
}
}
线程状态的转换:
线程的优先级:
线程的优先级越高,越有可能被执行(不是一定)
- 设置优先级:setPriority(int newPriority)
- 取得优先级:getPriority()
最高优先级:MAX_PRIOPITY = 10;
中等优先级: NORM_PRIOPITY = 5;
最低优先级: MIN_PRIOPITY = 1;
主方法的优先级是中等优先级,线程的优先级可以继承。比如在A线程中启动B线程,nameB线程优先级与A线程优先级相同