入坑JAVA多线程并发(四)卖火车票了解一下

多线程最常用的两个例子就是:火车票和生产者消费者问题了,本文简单的实现一下卖火车票的例子,
首先创建车票类:

class Ticket implements Runnable{

    private int num;
    private int init = 1;
    private String lock;

    public Ticket(int num,String lock){
        this.num = num;
        this.lock = lock;
    }

    @Override
    public void run() {
        while (true){    //这一行和下面不能交换,不然都是一个窗口把票卖完了
            synchronized (lock) {
                if (init > num) {
                    System.out.println("火车票已经卖完了");
                    return;
                }
                try {
                    //模拟出票过程,否则因为执行太快,大部分被一个线程执行完了
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "售出火车票:" + init++);
            }
        }
    }
}

测试方法:

public static void main(String[] args) throws InterruptedException {
        String  str = "lock";
        Ticket ticket = new Ticket(100,str);
        new Thread(ticket,"窗口A").start();
        new Thread(ticket,"窗口B").start();
        new Thread(ticket,"窗口C").start();
        new Thread(ticket,"窗口D").start();
    }

最终的指向结果为:

窗口A售出火车票:1
窗口A售出火车票:2
窗口A售出火车票:3
窗口A售出火车票:4
窗口A售出火车票:5
窗口A售出火车票:6
窗口A售出火车票:7
窗口A售出火车票:8
窗口A售出火车票:9
窗口A售出火车票:10
窗口A售出火车票:11
窗口A售出火车票:12
窗口A售出火车票:13
窗口A售出火车票:14
窗口A售出火车票:15
窗口A售出火车票:16
窗口A售出火车票:17
窗口A售出火车票:18
窗口A售出火车票:19
窗口A售出火车票:20
窗口A售出火车票:21
窗口A售出火车票:22
窗口A售出火车票:23
窗口A售出火车票:24
窗口A售出火车票:25
窗口A售出火车票:26
窗口D售出火车票:27
窗口D售出火车票:28
窗口D售出火车票:29
窗口D售出火车票:30
窗口D售出火车票:31
窗口D售出火车票:32
窗口D售出火车票:33
窗口C售出火车票:34
窗口C售出火车票:35
窗口C售出火车票:36
窗口C售出火车票:37
窗口C售出火车票:38
窗口C售出火车票:39
窗口C售出火车票:40
窗口C售出火车票:41
窗口C售出火车票:42
窗口C售出火车票:43
窗口C售出火车票:44
窗口C售出火车票:45
窗口C售出火车票:46
窗口C售出火车票:47
窗口C售出火车票:48
窗口C售出火车票:49
窗口C售出火车票:50
窗口C售出火车票:51
窗口C售出火车票:52
窗口C售出火车票:53
窗口C售出火车票:54
窗口C售出火车票:55
窗口C售出火车票:56
窗口C售出火车票:57
窗口C售出火车票:58
窗口C售出火车票:59
窗口C售出火车票:60
窗口C售出火车票:61
窗口C售出火车票:62
窗口C售出火车票:63
窗口C售出火车票:64
窗口C售出火车票:65
窗口C售出火车票:66
窗口C售出火车票:67
窗口C售出火车票:68
窗口C售出火车票:69
窗口C售出火车票:70
窗口C售出火车票:71
窗口C售出火车票:72
窗口C售出火车票:73
窗口C售出火车票:74
窗口C售出火车票:75
窗口C售出火车票:76
窗口C售出火车票:77
窗口C售出火车票:78
窗口C售出火车票:79
窗口C售出火车票:80
窗口C售出火车票:81
窗口C售出火车票:82
窗口C售出火车票:83
窗口C售出火车票:84
窗口C售出火车票:85
窗口C售出火车票:86
窗口C售出火车票:87
窗口C售出火车票:88
窗口C售出火车票:89
窗口C售出火车票:90
窗口C售出火车票:91
窗口C售出火车票:92
窗口C售出火车票:93
窗口C售出火车票:94
窗口C售出火车票:95
窗口C售出火车票:96
窗口C售出火车票:97
窗口C售出火车票:98
窗口C售出火车票:99
窗口C售出火车票:100
窗口B: 火车票已经卖完了
窗口C: 火车票已经卖完了
窗口D: 火车票已经卖完了
窗口A: 火车票已经卖完

虽然用sleep模拟了出票的过程,但是大部分票都被C窗口卖出去了,这里为了优化可以改成

 public void run() {
        while (true){
            synchronized (lock) {
                if (init > num) {
                    System.out.println(Thread.currentThread().getName()+": 火车票已经卖完了");
                    return;
                }
                try {
                    //模拟出票过程,否则因为执行太快,大部分被一个线程执行完了
                    lock.wait(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (init > num) {
                    System.out.println(Thread.currentThread().getName()+": 火车票已经卖完了");
                    return;
                }
                System.out.println(Thread.currentThread().getName() + "售出火车票:" + init++);
            }
        }
    }

这样子出票就很均匀了,而且在一个窗口进行操作的时候不会影响到其它窗口操作,输出就会不会出现大部分集中在一个窗口了。

你可能感兴趣的:(入坑JAVA多线程)