线程的状态有哪些? 它是如何工作的?
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();
-