1、线程的6种状态

  • Thread类中有个线程状态的枚举类型

    1. public class Thread implements Runnable {
    2. public enum State {
    3. NEW,
    4. RUNNABLE,
    5. BLOCKED,
    6. WAITING,
    7. TIMED_WAITING,
    8. TERMINATED;
    9. }
    10. }
  • 线程状态图

4-1、线程状态 - 图1

2、NEW(新建状态)

  • 线程对象被创建后,还没有调用start方法,就进入了新建状态

    1. Thread thread = new Thread();
    2. System.out.println(thread.getState());

    3、Runnable(可运行状态)

  • 这个状态的线程,其正在JVM中执行,但是这个”执行”,不一定是真的在运行, 也有可能是在等待CPU资源。所以,在网上,有人把这个状态区分为READY和RUNNING两个,一个表示的start了,资源一到位随时可以执行,另一个表示真正的执行中

    1. Thread thread = new Thread();
    2. thread.start();
    3. System.out.println(thread.getState());

4、Blocked(阻塞状态)

  • 这个状态,一般是线程等待获取一个锁,来继续执行下一步的操作,比较经典的就是synchronized关键字,这个关键字修饰的代码块或者方法,均需要获取到对应的锁,在未获取之前,其线程的状态就一直未BLOCKED,如果线程长时间处于这种状态下,我们就是当心看是否出现死锁的问题了
  • 下例输出结果

    Thread-0: start TIMED_WAITING BLOCKED Thread-0: end Thread-1: start Thread-1: end

  1. public class Main {
  2. public static void main(String[] args) {
  3. Object obj = new Object();
  4. MyThread thread1 = new MyThread(obj);
  5. thread1.start();
  6. MyThread thread2 = new MyThread(obj);
  7. thread2.start();
  8. try {
  9. Thread.sleep(1000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. // TIMED_WAITING
  14. System.out.println(thread1.getState());
  15. // BLOCKED
  16. System.out.println(thread2.getState());
  17. }
  18. public static class MyThread extends Thread {
  19. private Object obj;
  20. public MyThread(Object obj) {
  21. this.obj = obj;
  22. }
  23. @Override
  24. public void run() {
  25. synchronized (obj){
  26. System.out.println(Thread.currentThread().getName()+": start");
  27. try {
  28. Thread.sleep(10000);
  29. } catch (InterruptedException e) {
  30. e.printStackTrace();
  31. }
  32. System.out.println(Thread.currentThread().getName()+": end");
  33. }
  34. }
  35. }
  36. }

5、WAITING(无限等待)

  • WAITING状态的线程不再活动,不会浪费CPU资源,也不会去竞争锁;此状态下会等待别的线程执行notify通知,重新进入调度队列中
  • 一个线程进入WAITING无限等待状态,一定是执行了如下的代码

    • Object.wait()

      当一个线程执行了Object.wait()的时候,它一定在等待另一个线程执行Object.notify()或者Object.notifyAll()。

    • Thread.join()

      一个线程thread,其在主线程中被执行了thread.join()的时候,主线程即会等待该线程执行完成。

    • LockSupport.park()

      当一个线程执行了LockSupport.park()的时候,其在等待执行LockSupport.unpark(thread)。

  • 需要关注的是,这边的等待是没有时间限制的,当发现有这种状态的线程的时候,若其长时间处于这种状态,也需要关注下程序内部有无逻辑异常

    Object.wait()

  • 代码执行效果

    Thread-0: start 0 1 wait WAITING notify 2 3 4 Thread-0: end

  1. public class Main {
  2. public static void main(String[] args) throws InterruptedException {
  3. Object obj = new Object();
  4. MyThread thread1 = new MyThread(obj);
  5. thread1.start();
  6. Thread.sleep(4000);
  7. // WAITING
  8. System.out.println(thread1.getState());
  9. synchronized (obj){
  10. obj.notify();
  11. System.out.println("notify");
  12. }
  13. }
  14. public static class MyThread extends Thread {
  15. private Object obj;
  16. public MyThread(Object obj) {
  17. this.obj = obj;
  18. }
  19. @Override
  20. public void run() {
  21. synchronized (obj){
  22. System.out.println(Thread.currentThread().getName()+": start");
  23. for (int i = 0; i < 5; i++) {
  24. try {
  25. if (i == 2){
  26. System.out.println("wait");
  27. obj.wait();
  28. }
  29. Thread.sleep(1000);
  30. System.out.println(i);
  31. } catch (InterruptedException e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. System.out.println(Thread.currentThread().getName()+": end");
  36. }
  37. }
  38. }
  39. }

thread.join()

  • 执行结果

    thread1 start thread2 start thread1.join()后 , thread2 等待 thread1 执行完毕

thread1 end

thread1 执行完毕,thread2继续执行

thread2 end

  1. public class Main {
  2. public static void main(String[] args) throws InterruptedException {
  3. Thread1 thread1 = new Thread1();
  4. thread1.setName("thread1");
  5. thread1.start();
  6. Thread2 thread2 = new Thread2(thread1);
  7. thread2.setName("thread2");
  8. thread2.start();
  9. }
  10. public static class Thread1 extends Thread {
  11. public Thread1() {
  12. }
  13. @Override
  14. public void run() {
  15. System.out.println(Thread.currentThread().getName()+" start");
  16. try {
  17. Thread.sleep(3000);
  18. } catch (InterruptedException e) {
  19. e.printStackTrace();
  20. }
  21. System.out.println(Thread.currentThread().getName()+" end");
  22. }
  23. }
  24. public static class Thread2 extends Thread {
  25. private Thread thread1;
  26. public Thread2(Thread thread1) {
  27. this.thread1 = thread1;
  28. }
  29. @Override
  30. public void run() {
  31. System.out.println(Thread.currentThread().getName()+" start");
  32. try {
  33. System.out.println("thread1.join()后 , thread2 等待 thread1 执行完毕");
  34. // 等待thread1执行完毕后,当前线程(就是thread2)才会执行后续
  35. thread1.join();
  36. System.out.println("thread1 执行完毕,thread2继续执行");
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. System.out.println(Thread.currentThread().getName()+" end");
  41. }
  42. }
  43. }

LockSupport.park()

  • 代码执行结果

    Thread-0 start

WAITING

Thread-0 end

TERMINATED

  1. public class Main {
  2. public static void main(String[] args) throws InterruptedException {
  3. MyThread thread1 = new MyThread();
  4. thread1.start();
  5. Thread.sleep(100);
  6. // WAITING
  7. System.out.println(thread1.getState());
  8. // 唤醒线程
  9. LockSupport.unpark(thread1);
  10. Thread.sleep(100);
  11. // TERMINATED
  12. System.out.println(thread1.getState());
  13. }
  14. public static class MyThread extends Thread {
  15. @Override
  16. public void run() {
  17. System.out.println(Thread.currentThread().getName()+" start");
  18. // 阻塞线程
  19. LockSupport.park();
  20. System.out.println(Thread.currentThread().getName()+" end");
  21. }
  22. }
  23. }

6、TIMED_WAITING(计时等待)

  • 这个状态和WAITING状态的区别就是,这个状态的等待是有一定时效的,即可以理解为WAITING状态等待的时间是永久的,即必须等到某个条件符合才能继续往下走,否则线程不会被唤醒。但是TIMED_WAITING,等待一段时间之后,会唤醒线程去重新获取锁。当执行如下代码的时候,对应的线程会进入到TIMED_WAITING状态
  • 以下这几个方法都会导致线程进入TIMED_WAITING

    • Thread.sleep(long)
    • Object.wait(long)
    • Thread.join(long)
    • LockSupport.parkNanos()
    • LockSupport.parkUntil()

      Thread.sleep(long)

  • 下面代码执行结果

    Thread-0: start TIMED_WAITING

Thread-0: end

TERMINATED

  1. Thread thread = new Thread(new Runnable() {
  2. @Override
  3. public void run() {
  4. System.out.println(Thread.currentThread().getName()+": start");
  5. try {
  6. Thread.sleep(3000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println(Thread.currentThread().getName()+": end");
  11. }
  12. });
  13. thread.start();
  14. try {
  15. Thread.sleep(1000);
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. }
  19. // TIMED_WAITING
  20. System.out.println(thread.getState());
  21. try {
  22. Thread.sleep(3000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. // TERMINATED
  27. System.out.println(thread.getState());

obj.wait(long)

  • 代码执行结果

    Thread-0: start

0

1

wait sart

TIMED_WAITING

wait end

2

3

4

Thread-0: end

  1. public class Main {
  2. public static void main(String[] args) throws InterruptedException {
  3. Object obj = new Object();
  4. MyThread thread1 = new MyThread(obj);
  5. thread1.start();
  6. Thread.sleep(2000);
  7. // WAITING
  8. System.out.println(thread1.getState());
  9. }
  10. public static class MyThread extends Thread {
  11. private Object obj;
  12. public MyThread(Object obj) {
  13. this.obj = obj;
  14. }
  15. @Override
  16. public void run() {
  17. synchronized (obj){
  18. System.out.println(Thread.currentThread().getName()+": start");
  19. for (int i = 0; i < 5; i++) {
  20. try {
  21. if (i == 2){
  22. System.out.println("wait sart");
  23. obj.wait(3000);
  24. System.out.println("wait end");
  25. }
  26. System.out.println(i);
  27. } catch (InterruptedException e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. System.out.println(Thread.currentThread().getName()+": end");
  32. }
  33. }
  34. }
  35. }

7、TERMINATED(终止)

  • 线程执行结束之后的状态