1. 程式人生 > 其它 >多執行緒實現買票問題

多執行緒實現買票問題

實現Runnable介面的方式實現四個執行緒賣100張火車票的問題

點選檢視程式碼
public class TestTicket {

    public static void main(String[] args) {
        // 啟動四個執行緒賣票。
        TicketThread tt = new TicketThread();//一個執行緒物件

        new Thread(tt).start();//啟動四個執行緒,操作TicketThread類中的 tickets成員變數
        new Thread(tt).start();
        new Thread(tt).start();
        new Thread(tt).start();
    }
}
class TicketThread implements Runnable {
    // 100張票。
    private Integer tickets = 100;//爭用資源..
    @Override
    public void run() {
        while (tickets > 0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (this) {//臨界區,當某個執行緒進入臨界區後,其它執行緒必需等該執行緒執行完畢後,才有機會進入到該程式碼塊中
                    if(tickets>0) {//此處判斷是為了避免出現負數的情況
                        System.out.println(Thread.currentThread() + " is saling   ticket " + tickets);
                        tickets--;
                    }

                }
        }
    }
}
用繼承Thread類的方式實現四個執行緒賣100張火車票的問題---鎖的是自定義的執行緒類
點選檢視程式碼
public class TestTicket2 {
    public static void main(String[] args) {
        // 啟動四個執行緒賣票。
        TicketThread2 t1 = new TicketThread2();
        t1.start();

        TicketThread2 t2 = new TicketThread2();
        t2.start();

        TicketThread2 t3 = new TicketThread2();
        t3.start();

        TicketThread2 t4 = new TicketThread2();
        t4.start();

    }
}

class TicketThread2 extends  Thread {

    private  static  Integer tickets = 100;//靜態的變數隸屬於類,不屬於物件,多個物件共享的。

    @Override
    public void run() {
        while (tickets > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                /*
                    this代表當前物件,我們建立了四個TicketThread2類的物件,this分別程式碼這四個物件;
                    相當於有四個物件分別上鎖和開鎖(廁所有四個門),所以不可取;
                    所以我們得為共享靜態變數所屬於的類上鎖,即:TicketThread類上鎖。
                */
                synchronized (TicketThread2.class) {
                    if(tickets>0) {//此片判斷是為了避免出現負數的情況
                        System.out.println(Thread.currentThread() + "賣出了第" + tickets + "張票");
                        tickets--;
                    }
                }
           }

    }
}
用繼承Thread類的方式實現四個執行緒賣100張火車票的問題---鎖的是自定義的火車票類的物件
點選檢視程式碼
public class TestTicket3 {

    public static void main(String[] args) {

        Ticket ticket = new Ticket();
        ticket.tickets = 150;

        // 啟動四個執行緒賣票。
        TicketThread3 t1 = new TicketThread3(ticket);
        t1.start();

        TicketThread3 t2 = new TicketThread3(ticket);
        t2.start();

        TicketThread3 t3 = new TicketThread3(ticket);
        t3.start();

        TicketThread3 t4 = new TicketThread3(ticket);
        t4.start();

    }
}

//在Thread類中用成員代表火車票或定義靜態變數都不合適的情況下,我們可以把火車票單獨拿出來,然後傳入到執行緒類中
class Ticket{//代表火車票

    int tickets=100;

}

class TicketThread3 extends  Thread {

    Ticket ticket;

    public TicketThread3(Ticket ticket){
        this.ticket = ticket;
    }

    @Override
    public void run() {
        while (ticket.tickets > 0) {
            synchronized (ticket) {
                if(ticket.tickets>0) {//此片判斷是為了避免出現負數的情況
                    System.out.println(Thread.currentThread() + " 已賣   " + ticket.tickets);
                    ticket.tickets--;
                }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}