【多线程】卖票经典案例细述线程安全

场景

有三个售票窗口24小时无休的卖一百张车票。

版本一(有问题)

线程任务类

package lao.ben.juc.ticket;


public class Ticket implements Runnable {
          
   

    int num = 100;

    public void run() {
          
   
        while (true) {
          
   
            if (num > 0) {
          
   
                try {
          
   
                    Thread.sleep(50);
                } catch (InterruptedException e) {
          
   
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "在卖第 " + num + " 票。");
                num--;
            }
        }
    }
}

测试类

package lao.ben.juc.ticket;

public class TicketTest {
          
   

    public static void main(String[] args) {
          
   
        Ticket t = new Ticket();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }

}

所遇问题

重复卖

超卖

版本二(改进)

线程任务类

package lao.ben.juc.ticket;


@SuppressWarnings("all")
public class NewTicket implements Runnable {
          
   

    int num = 100;

    String s = "xiaolaoben";

    public void run() {
          
   
        while (true) {
          
   
            synchronized (s) {
          
   
                if (num > 0) {
          
   
                    try {
          
   
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
          
   
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "在卖第 " + num + " 票。");
                    num--;
                }
            }
        }
    }
}

测试类

package lao.ben.juc.ticket;

public class NewTicketTest {
          
   

    public static void main(String[] args) {
          
   
        NewTicket ticket = new NewTicket();
        new Thread(ticket).start();
        new Thread(ticket).start();
        new Thread(ticket).start();
    }
}

测试结果

经验分享 程序员 微信小程序 职场和发展