线程的状态有哪些? 它是如何工作的?
目录
- 线程的状态有哪些? 它是如何工作的?
- 1. 线程状态
- 2. 延伸面试题
1. 线程状态
public enum State {
/*
* 新建状态
* - 线程被创建出来, 但尚未启动时的线程状态
*/
NEW,
/*
* 就绪状态
* - 表示可以运行的线程状态, 它可能正在运行, 或者是在排队等待操作系统给它分配CPU资源
*/
RUNNABLE,
/*
* 阻塞等待锁的线程状态
* - 表示处于阻塞状态的线程正在等待监视器锁
* - 比如等待执行synchronized代码块或者使用synchronized标记的方法
*/
BLOCKED,
/*
* 等待状态
* - 一个处于等待状态的线程正在等待另一个线程执行某个特定的动作
* - 比如, 一个线程调用了Object.wait()方法
* - 那它就在等待另一个线程调用Object.notify()或Object.notifyAll()方法
*/
WAITING,
/*
* 计时等待状态
* - 和等待状态(WAITING)类似, 它只是多了超时时间
* - 比如调用了有超时时间设置的方法Object.wait(long timeout)
* 和 Thread.join(long timeout)等这些方法时它才会进入此状态
*/
TIMED_WAITING,
/*
* 终止状态
* - 表示线程已经执行完成
*/
TERMINATED
}
2. 延伸面试题
线程一般会作为并发编程的起始问题, 用于引出更多的关于并发编程的面试问题
- BLOCKED(阻塞等待) 和 WAITING(等待) 有什么区别?
- BLOCKED 处于活跃状态, 等待其他线程使用完锁资源后继续运行
- WAITING 处于休眠状态, 需被其他线程唤醒才能继续运行
- start() 方法和 run() 方法有什么区别?
- start()
- 属于Thread自身, 并且使用了synchronized来保证线程安全
- 可以开启多线程, 让线程从NEW状态转换成RUNNABLE状态
- 只可调用一次, 否则会抛出 java.lang.IllegalStateException
- run()
- 属于Runnable的抽象方法, 必须由调用类重写此方法
- 只是一个普通的方法
- 可以多次调用
- 线程的优先级有什么用? 该如何设置?
// 线程可以拥有的最小优先级
public final static int MIN_PRIORITY = 1;
// 线程默认优先级
public final static int NORM_PRIORITY = 5;
// 线程可以拥有的最大优先级
public final static int MAX_PRIORITY = 10;
// 通过Thread.setPriority()来设置优先级
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
// 先验证优先级的合理性
if(newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
// 优先级如果超过线程组的最高优先级, 则把优先级设置为线程组的最高优先级
if(newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
- 线程的常用方法有哪些?
- join()
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
// 超时时间不能小于0
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
// 等于0表示无限等待, 直到线程执行完为止
if (millis == 0) {
// 判断子线程(其他线程)为活跃线程, 则一直等待
while (isAlive()) {
wait(0);
}
} else {
// 循环判断
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
- yield()
// 由 C 或者 C++ 实现的
/*
* 给调度程序的提示是当前线程愿意放弃对处理器的当前使用。
* 调度程序可以随意忽略此提示。
* Yield是一种启发式尝试,旨在提高线程之间的相对进程,否则将过度利用CPU。
* 应将其使用与详细的性能分析和基准测试结合起来,以确保它实际上具有所需的效果。
* 很少适合使用此方法。
* 它可能对调试或测试有用,因为它可能有助于重现由于竞争条件而产生的错误。
* 当设计诸如{@link java.util.concurrent.locks}包中的并发控制结构时,它也可能很有用。
*/
public static native void yield();