11、多线程窗口销售火车票之初体验

版权声明:版权归 爱装逼的文艺小青年所有 https://blog.csdn.net/toyota_rav4/article/details/84844949

前面的博文中记录了一些关于多线程比较基础的一些API知识,本篇博文将在此基础上,整一个简单的模拟火车票销售的场景。此文只是简单的模拟,后续会对此进行改进!

package com.demo10;

public class Tickets extends Thread{
    private int lastTickets = 50;

    @Override
    public void run() {
        while (true) {
            if(lastTickets > 0){
                lastTickets--;
                System.out.println(Thread.currentThread().getName() + "卖出一张,余票:" + lastTickets + "张");
            }else{
                System.out.println("票已经卖完了!");
                Thread.currentThread().stop();
            }
        }
    }

}
package com.demo10;

public class Run {
    public static void main(String[] args) {
        Tickets tickets = new Tickets();
        Thread t1 = new Thread(tickets,"窗口A");
        Thread t2 = new Thread(tickets,"窗口B");
        Thread t3 = new Thread(tickets,"窗口C");
        t1.start();
        t2.start();
        t3.start();
    }
}

输出结果:

窗口A卖出一张,余票:49张
窗口A卖出一张,余票:48张
窗口A卖出一张,余票:47张
窗口A卖出一张,余票:46张
窗口A卖出一张,余票:45张
窗口A卖出一张,余票:44张
窗口A卖出一张,余票:43张
窗口A卖出一张,余票:42张
窗口A卖出一张,余票:41张
窗口A卖出一张,余票:40张
窗口A卖出一张,余票:39张
窗口A卖出一张,余票:38张
窗口A卖出一张,余票:37张
窗口A卖出一张,余票:36张
窗口A卖出一张,余票:35张
窗口A卖出一张,余票:34张
窗口B卖出一张,余票:33张
窗口A卖出一张,余票:32张
窗口B卖出一张,余票:31张
窗口A卖出一张,余票:30张
窗口B卖出一张,余票:29张
窗口A卖出一张,余票:27张
窗口C卖出一张,余票:27张
窗口A卖出一张,余票:25张
窗口B卖出一张,余票:26张
窗口A卖出一张,余票:23张
窗口C卖出一张,余票:24张
窗口A卖出一张,余票:21张
窗口B卖出一张,余票:22张
窗口A卖出一张,余票:19张
窗口C卖出一张,余票:20张
窗口A卖出一张,余票:17张
窗口B卖出一张,余票:18张
窗口A卖出一张,余票:15张
窗口C卖出一张,余票:16张
窗口A卖出一张,余票:13张
窗口B卖出一张,余票:14张
窗口A卖出一张,余票:11张
窗口C卖出一张,余票:12张
窗口A卖出一张,余票:9张
窗口B卖出一张,余票:10张
窗口A卖出一张,余票:7张
窗口C卖出一张,余票:8张
窗口A卖出一张,余票:5张
窗口B卖出一张,余票:6张
窗口A卖出一张,余票:3张
窗口C卖出一张,余票:4张
窗口A卖出一张,余票:1张
窗口B卖出一张,余票:2张
票已经卖完了!
票已经卖完了!
窗口C卖出一张,余票:0张
票已经卖完了!

从输出结果来看啊,三个卖票窗口(线程)启动之后,都在各卖各的,也不知道自己卖的票号是不是已经被其他窗口卖出去了,产生了多个窗口卖同一张票的错误。这是对消费者的一种欺骗啊。为了防止类似的事情发生,我们必须采取强烈的措施来对卖票窗口进行管理。目前采用的是加同步锁。意思就是 每一张票(资源)都是公平的摆在那里供三个窗口销售,但是只要某一个窗口抢先拿到了销售火车票(资源)的机会,就会把资源(火车票)锁住(加锁),让其他窗口(线程)无法对该资源进行操作,这样就不会出现乱套的现象了。只是加锁 ,使用完毕释放锁,对性能好像有一定的影响,后面在线程的高级阶段再来探讨。

对票采取同步操作 锁住this对象

package com.demo10;

public class Tickets extends Thread{
    private int lastTickets = 50;

    @Override
    public void run() {
        while (true) {
            synchronized (this){
                if(lastTickets > 0){
                    lastTickets--;
                    System.out.println(Thread.currentThread().getName() + 
                        "卖出一张,余票:" + lastTickets + "张");
                }else{
                    System.out.println("票已经卖完了!");
                    Thread.currentThread().stop();
                }
            }
        }
    }

}

运行结果:

窗口A卖出一张,余票:49张
窗口A卖出一张,余票:48张
窗口A卖出一张,余票:47张
窗口A卖出一张,余票:46张
窗口A卖出一张,余票:45张
窗口A卖出一张,余票:44张
窗口A卖出一张,余票:43张
窗口A卖出一张,余票:42张
窗口A卖出一张,余票:41张
窗口A卖出一张,余票:40张
窗口A卖出一张,余票:39张
窗口A卖出一张,余票:38张
窗口A卖出一张,余票:37张
窗口A卖出一张,余票:36张
窗口A卖出一张,余票:35张
窗口A卖出一张,余票:34张
窗口A卖出一张,余票:33张
窗口A卖出一张,余票:32张
窗口A卖出一张,余票:31张
窗口A卖出一张,余票:30张
窗口A卖出一张,余票:29张
窗口A卖出一张,余票:28张
窗口A卖出一张,余票:27张
窗口A卖出一张,余票:26张
窗口A卖出一张,余票:25张
窗口A卖出一张,余票:24张
窗口A卖出一张,余票:23张
窗口A卖出一张,余票:22张
窗口A卖出一张,余票:21张
窗口A卖出一张,余票:20张
窗口A卖出一张,余票:19张
窗口A卖出一张,余票:18张
窗口A卖出一张,余票:17张
窗口A卖出一张,余票:16张
窗口A卖出一张,余票:15张
窗口A卖出一张,余票:14张
窗口A卖出一张,余票:13张
窗口A卖出一张,余票:12张
窗口A卖出一张,余票:11张
窗口A卖出一张,余票:10张
窗口A卖出一张,余票:9张
窗口A卖出一张,余票:8张
窗口A卖出一张,余票:7张
窗口A卖出一张,余票:6张
窗口A卖出一张,余票:5张
窗口A卖出一张,余票:4张
窗口A卖出一张,余票:3张
窗口A卖出一张,余票:2张
窗口A卖出一张,余票:1张
窗口A卖出一张,余票:0张
票已经卖完了!
票已经卖完了!
票已经卖完了!

对票采取同步操作 锁住方法

package com.demo10;

public class Tickets extends Thread{
    private int lastTickets = 50;

    @Override
    public void run() {
        while (true) {
            sale();
        }
    }

    synchronized public void sale(){
        if(lastTickets > 0){
            lastTickets--;
            System.out.println(Thread.currentThread().getName() + 
                "卖出一张,余票:" + lastTickets + "张");
        }else{
            System.out.println("票已经卖完了!");
            Thread.currentThread().stop();
        }
    }
}

运行结果:

窗口A卖出一张,余票:49张
窗口A卖出一张,余票:48张
窗口B卖出一张,余票:47张
窗口B卖出一张,余票:46张
窗口B卖出一张,余票:45张
窗口B卖出一张,余票:44张
窗口B卖出一张,余票:43张
窗口B卖出一张,余票:42张
窗口B卖出一张,余票:41张
窗口B卖出一张,余票:40张
窗口B卖出一张,余票:39张
窗口B卖出一张,余票:38张
窗口B卖出一张,余票:37张
窗口C卖出一张,余票:36张
窗口C卖出一张,余票:35张
窗口C卖出一张,余票:34张
窗口C卖出一张,余票:33张
窗口C卖出一张,余票:32张
窗口C卖出一张,余票:31张
窗口C卖出一张,余票:30张
窗口C卖出一张,余票:29张
窗口C卖出一张,余票:28张
窗口C卖出一张,余票:27张
窗口C卖出一张,余票:26张
窗口C卖出一张,余票:25张
窗口C卖出一张,余票:24张
窗口C卖出一张,余票:23张
窗口C卖出一张,余票:22张
窗口C卖出一张,余票:21张
窗口C卖出一张,余票:20张
窗口C卖出一张,余票:19张
窗口C卖出一张,余票:18张
窗口C卖出一张,余票:17张
窗口C卖出一张,余票:16张
窗口C卖出一张,余票:15张
窗口C卖出一张,余票:14张
窗口C卖出一张,余票:13张
窗口C卖出一张,余票:12张
窗口C卖出一张,余票:11张
窗口C卖出一张,余票:10张
窗口C卖出一张,余票:9张
窗口C卖出一张,余票:8张
窗口C卖出一张,余票:7张
窗口C卖出一张,余票:6张
窗口C卖出一张,余票:5张
窗口C卖出一张,余票:4张
窗口C卖出一张,余票:3张
窗口C卖出一张,余票:2张
窗口C卖出一张,余票:1张
窗口C卖出一张,余票:0张
票已经卖完了!
票已经卖完了!
票已经卖完了!

猜你喜欢

转载自blog.csdn.net/toyota_rav4/article/details/84844949