Java 并发编程学习09 | java线程(上)总结
java 线程的状态
1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3. 阻塞(BLOCKED):表示线程阻塞于锁。
4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。6. 终止(TERMINATED):表示该线程已经执行完毕。
1. 初始状态
实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。
2.1. 就绪状态
- 就绪状态只是说你资格运行,调度程序没有挑选到你,你就永远是就绪状态。
- 调用线程的start()方法,此线程进入就绪状态。
- 当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。
- 当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。
- 锁池里的线程拿到对象锁后,进入就绪状态。
2.2. 运行中状态
线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。
Java 语言里则把可运行状态和运行状态合并了,这两个状态在操作系统调度层面有用,而 JVM 层面不关心这两个状态,因为 JVM 把线程调度交给操作系统处理了。
3. 阻塞状态
阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。
4. 等待
处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。
5. 超时等待
处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。
6. 终止状态
- 当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦终止了,就不能复生。
- 在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
让线程进入以上几种状态
1 static void NEW() { 2 Thread t = new Thread(); 3 System.out.println(t.getState()); 4 }
1 private static void RUNNABLE() { 2 Thread t = new Thread() { 3 public void run() { 4 for (int i = 0; i < 1; i++) { 5 System.out.println(this.getState()); 6 } 7 } 8 }; 9 t.start(); 10 }
3. BLOCKED, 这个就必须至少两个线程以上, 然后互相等待synchronized 块
1 // bolcked 2 private static void BLOCKED() { 3 final Object lock = new Object(); 4 Runnable run = new Runnable() { 5 @Override 6 public void run() { 7 System.out.println(Thread.currentThread().getState()); 8 for (int i = 0; i < Integer.MAX_VALUE; i++) { 9 synchronized (lock) { 10 if(i % 1000000 == 0){ 11 System.out.println(i); 12 } 13 } 14 } 15 } 16 }; 17 18 Thread t1 = new Thread(run); 19 t1.setName("t1"); 20 Thread t2 = new Thread(run); 21 t2.setName("t2"); 22 23 t1.start(); 24 t2.start(); 25 }
这时候, 一个在RUNNABLE, 另一个就会在BLOCKED (等待另一个线程的 System.out.println.. 这是个IO操作, 属于系统资源, 不会造成WAITING等)
4. WAITING, 这个需要用到生产者消费者模型, 当生产者生产过慢的时候, 消费者就会等待生产者的下一次notify
1 private static void WAITING() { 2 3 final Object lock = new Object(); 4 Thread t1 = new Thread() { 5 @Override 6 public void run() { 7 int i = 0; 8 while (true) { 9 synchronized (lock) { 10 try { 11 lock.wait(); 12 } catch (InterruptedException e) { 13 } 14 System.out.println(i++); 15 } 16 } 17 } 18 }; 19 20 Thread t2 = new Thread() { 21 @Override 22 public void run() { 23 while (true) { 24 synchronized (lock) { 25 for (int i = 0; i < 10000000; i++) { 26 System.out.println(i); 27 } 28 lock.notifyAll(); 29 } 30 } 31 } 32 }; 33 34 t1.setName("^^t1^^"); 35 t2.setName("^^t2^^"); 36 37 t1.start(); 38 t2.start(); 39 }
1 synchronized (lock) { 2 try { 3 lock.wait(60 * 1000L); 4 } catch (InterruptedException e) { 5 } 6 System. out .println(i++); 7 }
1 synchronized (lock) { 2 try { 3 sleep(30*1000L); 4 } catch (InterruptedException e) { 5 } 6 lock.notifyAll(); 7 }
1 private static void TERMINATED() { 2 Thread t1 = new Thread(); 3 t1.start(); 4 System.out.println(t1.getState()); 5 try { 6 Thread.sleep(1000L); 7 } catch (InterruptedException e) { 8 } 9 System.out.println(t1.getState()); 10 }
由于线程的start方法是异步启动的, 所以在其执行后立即获取状态有可能才刚进入RUN方法且还未执行完毕.
完整代码如下,顺带打印了pid,可以用 jstack pid 来查看信息
1 package com.test.thread; 2 3 import java.lang.management.ManagementFactory; 4 5 public class TestThread { 6 // 初始状态 7 static void NEW() { 8 Thread t = new Thread(); 9 System.out.println(t.getState()); 10 } 11 12 // 运行状态 13 private static void RUNNABLE() { 14 Thread t = new Thread() { 15 public void run() { 16 for (int i = 0; i < 1; i++) { 17 System.out.println(this.getState()); 18 } 19 } 20 }; 21 t.start(); 22 } 23 24 // bolcked 25 private static void BLOCKED() { 26 final Object lock = new Object(); 27 Runnable run = new Runnable() { 28 @Override 29 public void run() { 30 System.out.println(Thread.currentThread().getState()); 31 for (int i = 0; i < Integer.MAX_VALUE; i++) { 32 synchronized (lock) { 33 if(i % 1000000 == 0){ 34 System.out.println(i); 35 } 36 } 37 } 38 } 39 }; 40 41 Thread t1 = new Thread(run); 42 t1.setName("t1"); 43 Thread t2 = new Thread(run); 44 t2.setName("t2"); 45 46 t1.start(); 47 t2.start(); 48 } 49 50 private static void WAITING() { 51 52 final Object lock = new Object(); 53 Thread t1 = new Thread() { 54 @Override 55 public void run() { 56 int i = 0; 57 while (true) { 58 synchronized (lock) { 59 try { 60 lock.wait(); 61 } catch (InterruptedException e) { 62 } 63 System.out.println(i++); 64 } 65 } 66 } 67 }; 68 69 Thread t2 = new Thread() { 70 @Override 71 public void run() { 72 while (true) { 73 synchronized (lock) { 74 for (int i = 0; i < 10000000; i++) { 75 System.out.println(i); 76 } 77 lock.notifyAll(); 78 } 79 } 80 } 81 }; 82 83 t1.setName("^^t1^^"); 84 t2.setName("^^t2^^"); 85 86 t1.start(); 87 t2.start(); 88 } 89 90 private static void TIMED_WAITING() { 91 92 final Object lock = new Object(); 93 Thread t1 = new Thread() { 94 @Override 95 public void run() { 96 int i = 0; 97 while (true) { 98 synchronized (lock) { 99 try { 100 lock.wait(60 * 1000L); 101 } catch (InterruptedException e) { 102 } 103 System.out.println(i++); 104 } 105 } 106 } 107 }; 108 109 Thread t2 = new Thread() { 110 @Override 111 public void run() { 112 while (true) { 113 synchronized (lock) { 114 for (int i = 0; i < 10000000; i++) { 115 System.out.println(i); 116 } 117 lock.notifyAll(); 118 } 119 } 120 } 121 }; 122 123 t1.setName("^^t1^^"); 124 t2.setName("^^t2^^"); 125 126 t1.start(); 127 t2.start(); 128 } 129 130 private static void TERMINATED() { 131 Thread t1 = new Thread(); 132 t1.start(); 133 System.out.println(t1.getState()); 134 try { 135 Thread.sleep(1000L); 136 } catch (InterruptedException e) { 137 } 138 System.out.println(t1.getState()); 139 } 140 141 142 public static void main(String[] args) { 143 String name = ManagementFactory.getRuntimeMXBean().getName(); 144 System.out.println(name); 145 String[] names = name.split("@"); 146 int pid = Integer.parseInt(names[0]); 147 System.out.println("pid: " + pid); 148 149 NEW(); 150 RUNNABLE(); 151 BLOCKED(); 152 153 TERMINATED(); 154 } 155 }