静态同步方法以及Lock锁以及线程状态概述

静态同步方法

复制代码
class RunnaleImpl implements Runnable{
    //定义一个多个线程共享的票源
    private static int ticket = 100;
    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环让卖票操作重复执行
        while (true){
            payTicket();
        }
    }
    //定义一个同步方法
    public static synchronized void payTicket(){
        //判断票是否存在
        if (ticket>0){
            //提高安全问题出现的概率,让程序睡眠
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //票存在,卖票,ticket--
            System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
            ticket--;
        }
    }
}
复制代码
复制代码
public class Demo01Ticket {
    /**
     * 模拟卖票案例
     * 创建3个线程,同时开启,对共享的票进行出售
     */
    public static void main(String[] args) {
        RunnaleImpl ru = new RunnaleImpl();
        Thread t0 = new Thread(ru);
        Thread t1 = new Thread(ru);
        Thread t2 = new Thread(ru);
        t0.start();
        t1.start();
        t2.start();
    }
}
复制代码

静态同步方法的锁对象不能是this。

this是创建对象之后产生的,静态方法优先于对象

静态方法的锁对象是本类的class属性——>class文件对象

复制代码
    //定义一个同步方法
    public static /*synchronized*/ void payTicket(){
        synchronized (RunnaleImpl.class){
            //判断票是否存在
            if (ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //票存在,卖票,ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }
    }
}
复制代码

 

 

 

 

 

解决线程安全问题—Lock锁

一、Lock锁

  虽然我们可以理解同步代码块和同步方法的锁对象问题,但是我们并没有直接看到在哪里上了锁,在哪里释放了锁,为了更清晰的表达如何加锁和释放锁,JDK5以后提供了一个新的锁对象Lock

  Lock实现提供比使用synchronized方法和语句更广泛的锁定操作

二、Lock中提供了获得锁和释放锁的方法

  1.void lock():获得锁

  2.void unlock();释放锁

  Lock由于是接口,不能直接实例化,这里采用它的实现类ReentrantLock来实例化

三、ReentrantLock的构造方法

  ReentrantLock():创建一个ReentrantLock的实例

使用步骤:
  1.在成员位置创建一个ReentrantLock对象

  2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁

  3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁

复制代码
class RunnaleImpl implements Runnable{
    //定义一个多个线程共享的票源
    private static int ticket = 100;

    //1.在成员位置创建一个ReentrantLock对象
    Lock l = new ReentrantLock();

    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环让卖票操作重复执行
        while (true){
            //2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
            l.lock();

            //判断票是否存在
            if (ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //票存在,卖票,ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }

            //3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁
            l.unlock();
        }
    }
}
复制代码

添加Lock锁之后,程序照样不会出现重票的和不存在票的现象

复制代码
 @Override
    public void run() {
        //使用死循环让卖票操作重复执行
        while (true){
            //2.在可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
            l.lock();

            //判断票是否存在
            if (ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                    //票存在,卖票,ticket--
                    System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                    ticket--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }finally {
                    //3.在可能会出现安全问题的代码后调用Lock接口中的方法unLock释放锁
                    l.unlock();
                }
            }
        }
    }
复制代码

同样也可以将unlock写在finally代码块中,这样不管程序会不会出现异常都会释放锁,可以提高程序的效率

 

 

 

 

 

 

线程状态概述

 

线程状态 导致状态发生条件
NEW(新建) 线程刚被创建,但是并未其中。还没调用start方法。
Runnable(可运行)

线程可以在java虚拟机中运行的状态,可能正在运行自己的代码,也可能没有,取决于操作系统处理器

Blocked(锁阻塞)

当一个线程视图获取一个锁对象,而该对象锁被其他的线程持有,则该线程进入Blocked状态;

当该线程持有锁时,该线程将变成Runnable状态

Waiting(无限等待)

一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,

必须等待另一个线程调用notify或者notifyAll方法才能够唤醒。

Timed Waiting(计时等待)

同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep 、object.wait。

Teminated(被阻止) 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

阻塞状态:具有cpu的执行资格,等待cpu空闲时执行

休眠状态:放弃cpu的执行资格, cpu空闲,也不执行

 

posted @   xjw12345  阅读(97)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示