volatile和synchronized同步的实例

经典案例 – Java·卖票问题

实现卖票中多个窗口同时买一张票,实际100张票卖出去100多张票等一系列问题

volatile

//volatile关键字在卖票例子中表现
public class TicketWindows implements Runnable {
    private volatile int ticket = 100; // 一百张票,用volatile修饰
    @Override
    public void run() {
        // 重写run方法,模拟卖票,通过下面我们可以发现:对一个共享资源可以多个线程同时进行修改,自然就会有线程安全问题。
        while (true){
            if (ticket > 0){
                try {
                    Thread.sleep(100); //多个线程同时判断到“ticket>0”,然后休眠
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                //多个线程同时唤醒,并且同时进行ticket--操作
                System.out.println(Thread.currentThread().getName() + "卖出一张票,当前票数:" + ticket--);
            }else break;
        }
    }
}
//测试类
public class TestVolatile {
    public static void main(String[] args) {
       TicketWindows tw = new TicketWindows();
       Thread t1 = new Thread(tw);
       Thread t2 = new Thread(tw);
       Thread t3 = new Thread(tw);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

[外链图片转存中…(img-QSAv3lvm-1724572491379)]

synchronized

//卖票窗口
public class Ticket {
    static int tCount = 100; // 默认票数100张

    public synchronized boolean gettCount() {
        //返回是否有余票
        return tCount > 0;
    }

    public synchronized void saleT(int n, String name) {
        if (tCount - n >= 0) {
            tCount -= n;
            System.out.println(name + ":出售" + n + "张票成功!目前还剩" + tCount + "张票~");
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (tCount != 0) {
            //如果第一个判断买票数量大于余票数量,但还有票
            System.out.println(name +":抱歉!购买" + n + "张票失败!目前仅剩" + tCount + "张!");
        } else System.out.println(name +":抱歉!票已售空~");
    }
}
//测试类
public class TestBuyTicket {
    public static void main(String[] args) {
        // 创建售票对象
        Ticket ticket = new Ticket();
        // 创建3个售票窗口线程
        Thread ck1 = new Thread("窗口1") {
            @Override
            public void run() {
                while (ticket.gettCount())
                    // 限制每次购票最多5张
                    ticket.saleT((int) (Math.random() * 5) + 1, Thread.currentThread().getName());
            }
        };
        Thread ck2 = new Thread("窗口2") {
            @Override
            public void run() {
                while (ticket.gettCount())
                    // 限制每次购票最多5张
                    ticket.saleT((int) (Math.random() * 5) + 1, Thread.currentThread().getName());
            }
        };
        Thread ck3 = new Thread("窗口3") {
            @Override
            public void run() {
                while (ticket.gettCount())
                    // 限制每次购票最多5张
                    ticket.saleT((int) (Math.random() * 5) + 1, Thread.currentThread().getName());
            }
        };
        ck1.start();
        ck2.start();
        ck3.start();
    }
}

   }
    };
    ck1.start();
    ck2.start();
    ck3.start();
}

}
在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值