1. 程式人生 > >入坑JAVA多執行緒併發(四)賣火車票瞭解一下

入坑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++);
            }
        }
    }

這樣子出票就很均勻了,而且在一個視窗進行操作的時候不會影響到其它視窗操作,輸出就會不會出現大部分集中在一個視窗了。