本文介绍了java线程的生命周期,Synchronized的几个方法简单的使用。
线程生命周期
-
初始状态(New)
New Thread之后,
-
就绪状态(Ready)
表示获取到了Cpu的执行时间片,也就是cpu的执行权,等待开始执行。
-
运行状态(Runable)
执行start之后,开始运行。
-
阻塞状态(Blocked)
在进入synchronized的临界区或者Lock的临界区,等待获取监视器(monitor)锁,线程会进入同步队列(SynchronizedQueue)中。
-
等待状态:(Waiting)
在执行await(),wait(),jion(),LockSupport.park()方法进入等待状态;
-
等待超时状态
在执行Object.await(time), Object.wait(time), Object.sellp(time), LockSupport.parkUntil,lockSupport.parkNanos 进入等待超时状态。
-
终止状态
线程执行完毕或者执行了Thread.interrupt() / Thread.stop(),不建议使用的Thread.stop() 因为 Thread.stop是直接强行结束,不会释放资源 ;
-
配图
锁的几个简单方法
-
wait 和 notify/notifyAll
解释
wait: 将线程状态置位 '等待状态',进入等待队列等待。
notify/notifyAll: notify是随机唤醒一个线程进入 '同步队列',notifyAll是唤醒全部被监视器锁wait的线程进入 '同步队列',等待获取监视器锁后继续执行。提示:wait,notify/notifyAll都需要在获取到监视器所(monitor)后才可以进行操作。
代码
public class WaitAndNotifyTest { private static Object obj = new Object(); public static void main(String[] args) { // 创建线程 thread1 Thread thread1 = new Thread(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " begin wait..."); synchronized (obj) { obj.wait(); } System.out.println(Thread.currentThread().getName() + " end wait..."); } catch (Exception e) { e.printStackTrace(); } } }, "thread1"); // 创建线程 thread2 Thread thread2 = new Thread(new Runnable() { @Override public void run() { try { System.out.println(Thread.currentThread().getName() + " begin wait..."); synchronized (obj) { obj.wait(); } System.out.println(Thread.currentThread().getName() + " end wait..."); } catch (Exception e) { e.printStackTrace(); } } }, "thread2"); // 启动 thread1.start(); thread2.start(); try { // 睡眠一秒 Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } // 下面我们加上 obj.notify() 就会先输出 begin wait 然后sellp 10秒,执行obj.notify() 唤醒 thread1 线程 , 输出end wait // obj 上可能会存在wait 多个线程, notify唤醒是随机的,不一定能唤醒哪一个线程 // 如果调用 notify 的线程未获取 对象锁,在调用 notify 的时候会抛出 java.lang.IllegalMonitorStateException 异常 synchronized (obj) { // 唤醒 使用呢 obj 调用 wait 方法的其中一个线程 (随机) obj.notify(); // 唤醒 使用呢 obj 调用 wait 方法的所有线程 obj.notifyAll(); } } }
执行结果: thread2 begin wait... thread1 begin wait... thread1 end wait... thread2 end wait...
-
await,signal/signalAll
解释
await,signal/signalAll方法是Lock Condition的方法,语义和Object的wait,notify/notifyAll是完全相同的。
代码
/** * @Auther: lantao * @Date: 2019-04-15 14:49 * @Company: * @maill: * @Description: Condition 条件 有 singal signalAll 和 await 方法 和Object 的 notify notifyAll 和 wait 是一个意思同样会释放锁 执行singal和notify的时候也需要在等待获取锁 */ public class LockCondition { public static ReentrantLock lock = new ReentrantLock(); public static Condition a = lock.newCondition(); public static void main(String[] args) throws InterruptedException { Runnable runnable = () -> { try { lock.lock(); System.out.println(Thread.currentThread().getName()); System.out.println("1"); a.await(); System.out.println(Thread.currentThread().getName() + "被唤醒了"); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } }; Runnable runnable1 = () -> { try { lock.lock(); System.out.println("线程" +Thread.currentThread().getName() + "开始执行sinal"); a.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } }; new Thread(runnable,"Thread1").start(); new Thread(runnable,"Thread2").start(); Thread.sleep(100); new Thread(runnable1,"Thread3").start(); } }
执行结果: Thread1 Thread2 线程Thread3开始执行sinal Thread1被唤醒了 Thread2被唤醒了
-
Join 和 Join(time)
解释
等待调用Join的线程执行完成后再继续执行,或者等待时间超过了超时时间继续执行;
代码
/** * @Auther: lantao * @Date: * @Company: * @maill: * @Description: Join 核心是等待指定线程运行完后再继续运行 Join(time) 就是等待线程执行的一个超时时间 超过了就继续执行了 */ public class JoinTest { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(new Runnable() { @Override public void run() { System.out.println("1"); try { Thread.sleep(2000L); System.out.println("正常完成"); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("2"); } }); thread1.start(); // 执行 jion 等待线程 thread1 执行完后再继续执行 thread1.join(); // thread1.join(1000); // 这样最终执行的顺序是 1 2 3 如果不增加 thread1.join() 结果可能是 312 也可能是 132 // Join 核心是等待指定线程运行完后再继续运行 System.out.println("3"); } }
执行结果: 1 正常完成 2 3
-
yield
解释
yeid 方法的核心是让出 cpu 时间片 ,也就是cpu执行权,线程会直接进入就绪状态,线程调度器会从线程就绪队列里获取一个线程优先级最高的线程来执行,当然也有可能直接会去到刚刚让出cpu执行权的线程,继续执行yield 后续的代码。
代码
/** * @Auther: lantao * @Date: 2019-03-25 17:20 * @Company: * @maill: * @Description: */ public class YieldTest { private static Object obj = new Object(); public static void main(String[] args) { Thread thread1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 开始执行 yield "); Thread.yield(); System.out.println("trhead1"); } } } }, "thread1"); Thread thread2 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 开始执行 yield "); Thread.yield(); System.out.println("trhead2"); } } } }, "thread2"); Thread thread3 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 5; i++) { if (0 / 5 == i) { System.out.println(Thread.currentThread().getName() + " 开始执行 yield "); Thread.yield(); System.out.println("trhead3"); } } } }, "thread3"); // 执行三个线程, 正常当运行到yield 是 就会让出cpu执行权,线程到 就绪状态,线程调度器会从 线程就绪队列里获取一个线程优先级最高的线程来执行, // 当然也有可能直接会去到刚刚让出cpu的线程,继续执行yield 后续的代码 thread1.start(); thread3.start(); thread2.start(); } }
执行结果: thread1 开始执行 yield thread2 开始执行 yield thread3 开始执行 yield trhead2 trhead1 trhead3
-
interrupt 和 stop
解释
interrupt和stop都代表中断线程,区别是 interrupt 会释放资源而stop不会,interrupt也不会立马就中断;说道interrupt就得说一下isInterrupted方法,他是判断线程中断标志的,如果线程A执行了线程B的interrupt方法,线程B在自己的线程中也可以使用 isInterrupted 方法判断自己的中断标志。
注意:在使用 interrupt方法时,如果线程在sleep wait wait(time)状态, 抛出InterruptedException异常后会清除 isInterrupted 方法获取的中断标志位,反之则不会代码
/** * @Auther: lantao * @Date: 2019-04-17 17:18 * @Company: * @maill: * @Description: 在使用 interrupt方法是,如果线程咋sleep wait wait(time) 在抛出InterruptedException异常后会 清除 isInterrupted 方法获取的标志位 其他则不会 */ public class InterruptTest { public static void main(String[] args) throws InterruptedException { Thread thread1 = new Thread(() -> { while (true) {} }, "循环线程"); Thread thread2 = new Thread(() -> { while (true) { try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } }, "睡眠线程"); Thread thread3 = new Thread(() -> { Object o = new Object(); while (true) { synchronized (o){ try { o.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "等待线程"); thread1.start(); thread2.start(); thread3.start(); Thread.sleep(500); thread1.interrupt(); thread2.interrupt(); thread3.interrupt(); Thread.sleep(500); System.out.println("循环线程isInteryupt is " + thread1.isInterrupted()); System.out.println("睡眠线程isInteryupt is " + thread2.isInterrupted()); System.out.println("等待线程isInteryupt is " + thread3.isInterrupted()); } }
执行结果: java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.com.concurrenncy.InterruptTest.lambda$main$1(InterruptTest.java:20) at java.lang.Thread.run(Thread.java:748) java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.com.concurrenncy.InterruptTest.lambda$main$2(InterruptTest.java:32) at java.lang.Thread.run(Thread.java:748) 循环线程isInteryupt is true 睡眠线程isInteryupt is false 等待线程isInteryupt is false