當前位置:
首頁 >
【Java多线程】并发时的线程安全:快乐影院示例
發布時間:2024/2/28
49
豆豆
生活随笔
收集整理的這篇文章主要介紹了
【Java多线程】并发时的线程安全:快乐影院示例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
快樂影院示例
如果去掉71行的synchronized,會導致線程不安全
結果就是:明明已經沒有票(有人搶先一步),卻又被成功訂走了。圖見文末
下面是正確的代碼:
package cn.hanquan.test;import java.util.ArrayList; import java.util.List;public class HappyCinema {public static void main(String[] args) throws InterruptedException {// 可用位置List<Integer> seats = new ArrayList<Integer>();for (int i = 1; i <= 10; i++)seats.add(i);// 預定位置List<Integer> aWant = new ArrayList<Integer>();aWant.add(1);aWant.add(3);List<Integer> bWant = new ArrayList<Integer>();bWant.add(2);bWant.add(6);List<Integer> cWant = new ArrayList<Integer>();cWant.add(6);cWant.add(7);cWant.add(2);Cinema cm = new Cinema("HappyCinema", seats);Customer a = new Customer(cm, aWant);Customer b = new Customer(cm, bWant);Customer c = new Customer(cm, cWant);a.start();b.start();c.start();Thread.sleep(300);} }class Customer extends Thread {Cinema cinema;List<Integer> want = new ArrayList<Integer>();public Customer(Cinema cinema, List<Integer> want) {this.cinema = cinema;this.want = want;}@Overridepublic void run() {boolean flag = cinema.bookTickets(want);if (flag) {System.out.println("√ 訂票成功 " + Thread.currentThread().getName() + " 你定的 " + want + " 訂后剩余 " + cinema.seats);} else {System.out.println("× 訂票失敗 " + Thread.currentThread().getName() + " 你定的 " + want + " 訂后剩余 " + cinema.seats);}} }class Cinema extends Thread {String name;List<Integer> seats;public Cinema(String name, List<Integer> seats) {System.out.println("歡迎來到:" + name + " 初始化座位:" + seats);this.name = name;this.seats = seats;}public synchronized boolean bookTickets(List<Integer> want) {// System.out.println("空余位置:" + seats);List<Integer> copy = new ArrayList<Integer>();copy.addAll(seats);copy.removeAll(want);if (seats.size() - want.size() == copy.size()) {try {Thread.sleep(50);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}seats = copy;return true;} else {return false;}} }運行結果
由于線程由操作系統調度,搶票的結果隨機。
但經過多次試驗,發現大多數情況下,先start()的線程先執行。
偶爾出現下列結果:
大多數時候是下列結果:
附:錯誤的執行結果如果(去掉71行的synchronized)
快樂火車站示例
36行,Thread是可以被強制類型轉換的
package cn.hanquan.test;public class HappyTrain {public static void main(String[] args) throws InterruptedException {Station station = new Station(20, "HappStation");Passenger p1 = new Passenger(station, "猿", 8);Passenger p2 = new Passenger(station, "傻子", 3);Passenger p3 = new Passenger(station, "魚", 11);p1.start();p2.start();p3.start();} }// 作為代理 寫成 extends Thread class Passenger extends Thread {// extends 繼承類int want;// 可以定義線程變量public Passenger(Runnable target, String name, int seats) {super(target, name);// 將父類的構造器延續下來this.want = seats;// 同時自己加入屬性} }class Station implements Runnable {// implements 實現接口int seats;String name;public Station(int seats, String name) {System.out.println("歡迎來到 " + name + " 初始化座位:" + seats);this.seats = seats;this.name = name;}@Overridepublic void run() {Passenger p = (Passenger) Thread.currentThread();// 對應于p1.start(); 強轉回調用start()的類boolean success = this.buyTickets(p.want);if (success) {System.out.println("√ 購票成功 " + Thread.currentThread().getName() + "\t購買:" + p.want + " 成交后剩余:" + seats);} else {System.out.println("× 購票失敗 " + Thread.currentThread().getName() + "\t購買:" + p.want + " 實際剩余:" + seats);}}public synchronized boolean buyTickets(int want) {// System.out.println("剩余位置:" + seats);if (seats > want) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}seats -= want;return true;} else {return false;}} }運行結果
總結
以上是生活随笔為你收集整理的【Java多线程】并发时的线程安全:快乐影院示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Java线程安全】 synchroni
- 下一篇: 【Java线程安全】一个简单的多线程程序