Java面向对象之线程的生命周期、线程的同步、互斥锁、线程的死锁及释放锁

Java面向对象之线程的生命周期、线程的同步、互斥锁、线程的死锁及释放锁,第1张

Java面向对象之线程的生命周期、线程的同步、互斥锁、线程的死锁及释放锁

文章目录
      • 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、下面 *** 作不会释放锁

1、线程的生命周期 1.1、JDK 中用 Thread.State 枚举表示了线程的几种状态

1.2、线程状态转换图

1.3、查看线程状态
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、下面 *** 作不会释放锁

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5686548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存