- 1、线程的生命周期
- 1.1、JDK 中用 Thread.State 枚举表示了线程的几种状态
- 1.2、线程状态转换图
- 1.3、查看线程状态
- 2、线程的同步
- 2.1、问题引出
- 2.2、Synchronized
- 2.2.1、线程同步机制
- 2.2.2、同步具体方法 - Synchronized
- 2.2.3、分析同步原理
- 3、互斥锁
- 3.1、基本介绍
- 3.2、使用互斥锁来解决售票问题
- 3.3、注意事项和细节
- 4、线程的死锁
- 4.1、基本介绍
- 4.2、形象的比喻
- 4.3、代码实现
- 5、释放锁
- 5.1、下面 *** 作会释放锁
- 5.2、下面 *** 作不会释放锁
package state_; public class ThreadState_ { public static void main(String[] args) throws InterruptedException { T t = new T(); System.out.println(t.getName() + "状态: " + t.getState()); // Thread-0状态: NEW t.start(); while (Thread.State.TERMINATED != t.getState()) { System.out.println(t.getName() + "状态: " + t.getState()); Thread.sleep(500); } System.out.println(t.getName() + "状态: " + t.getState()); // Thread-0状态: TERMINATED } } class T extends Thread { @Override public void run() { while (true) { for (int i = 0; i < 10; i++) { System.out.println("hi " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } break; } } }2、线程的同步 2.1、问题引出 2.2、Synchronized 2.2.1、线程同步机制 2.2.2、同步具体方法 - Synchronized 2.2.3、分析同步原理 3、互斥锁 3.1、基本介绍 3.2、使用互斥锁来解决售票问题
package syn; public class SellTicket { public static void main(String[] args) { // 测试 // 测试一把 SellTicket03 sellTicket03 = new SellTicket03(); new Thread(sellTicket03).start(); // 第1个线程-窗口 new Thread(sellTicket03).start(); // 第2个线程-窗口 new Thread(sellTicket03).start(); // 第3个线程-窗口 } } // 实现接口方式, 使用synchronized实现线程同步 class SellTicket03 implements Runnable { private int ticketNum = 100; // 让多个线程共享 ticketNum private boolean loop = true; // 控制run方法变量 Object object = new Object(); // 同步方法(静态的)的锁为当前类本身 // 解读 // 1. public synchronized static void m1() {} 锁是加在 SellTicket03.class // 2. 如果在静态方法中, 实现一个同步代码块 public synchronized static void m1() { } public static void m2() { synchronized (SellTicket03.class) { System.out.println("m2"); } } // 1. public synchronized void sell() {} 就是一个同步方法 // 2. 这时锁在 this对象 // 3. 也可以在代码块上写 synchronize, 同步代码块, 互斥锁还是在this对象 public void sell() { // 同步方法, 在同一时刻, 只能有一个线程来执行sell方法 synchronized (object) { if (ticketNum <= 0) { System.out.println("售票结束..."); loop = false; return; } // 休眠50毫秒, 模拟 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum)); } } @Override public void run() { while (loop) { sell(); // sell方法是一共同步方法 } } } class SellTicket01 extends Thread { private static int ticketNum = 100; // 让多个线程共享 ticketNum @Override public void run() { while (true) { if (ticketNum <= 0) { System.out.println("售票结束..."); break; } // 休眠50毫秒, 模拟 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum)); } } } // 实现接口方式 class SellTicket02 implements Runnable { private int ticketNum = 100; // 让多个线程共享 ticketNum @Override public void run() { while (true) { if (ticketNum <= 0) { System.out.println("售票结束..."); break; } // 休眠50毫秒, 模拟 try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票" + " 剩余票数=" + (--ticketNum)); } } }3.3、注意事项和细节 4、线程的死锁 4.1、基本介绍
4.2、形象的比喻多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生
4.3、代码实现妈妈:你先完成作业,才让你玩手机
小明:你先让我玩手机,我才完成作业
package syn; public class DeadLock_ { public static void main(String[] args) { // 模拟死锁现象 DeadLockDemo A = new DeadLockDemo(true); A.setName("A 线程"); DeadLockDemo B = new DeadLockDemo(false); B.setName("B 线程"); A.start(); B.start(); // 控制台输出 } } // 线程 class DeadLockDemo extends Thread { static Object o1 = new Object(); // 保证多线程, 共享一个对象,这里使用 static static Object o2 = new Object(); boolean flag; public DeadLockDemo(boolean flag) { // 构造器 this.flag = flag; } @Override public void run() { // 下面业务逻辑的分析 // 1. 如果 flag 为 T, 线程 A 就会先得到/持有 o1 对象锁, 然后尝试去获取 o2 对象锁 // 2. 如果线程 A 得不到 o2 对象锁, 就会 Blocked // 3. 如果 flag 为 F, 线程 B 就会先得到/持有 o2 对象锁, 然后尝试去获取 o1 对象锁 // 4. 如果线程 B 得不到 o1 对象锁,就会 Blocked if (flag) { synchronized (o1) { // 对象互斥锁, 下面就是同步代码 System.out.println(Thread.currentThread().getName() + " 进入 1"); synchronized (o2) { // 这里获得 li 对象的监视权 System.out.println(Thread.currentThread().getName() + " 进入 2"); } } } else { synchronized (o2) { System.out.println(Thread.currentThread().getName() + " 进入 3"); synchronized (o1) { // 这里获得 li 对象的监视权 System.out.println(Thread.currentThread().getName() + " 进入 4"); } } } } }5、释放锁 5.1、下面 *** 作会释放锁 5.2、下面 *** 作不会释放锁
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)