マルチスレッドチケット販売

仮定映画館で映画を見せている、と映画が持つ100枚の売却可能映画のチケットを。今そこにあるとし3つのチケットを販売するウィンドウが。ウィンドウチケットのシーンをシミュレートするプログラムを設計してください。

分析:

3つのウィンドウは相互に影響を与えず、同時にチケット販売します

これらの100本の映画チケットを一緒販売する3つのウィンドウ

マルチスレッドを実装する方法は次の2つですが、すべて問題があります(チケットが重複して販売され、存在しないチケットが販売され、チケットの順序が間違っています)。

            部分的な結果

//方式一:将类声明为Thread的子类
public class Test {
    public static void main(String[] args) {
        //创建线程对象
        SellTicket t1 = new SellTicket();
        SellTicket t2 = new SellTicket();
        SellTicket t3 = new SellTicket();
        //各线程起名字
        t1.setName("一号窗口");
        t2.setName("二号窗口");
        t3.setName("三号窗口");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}

class SellTicket extends Thread {
    static int ticket = 100;//初始有100张票
    @Override
    public void run() {
        while (ticket > 0) {//一直卖票,直到票卖完
            try {//模拟选中票后的网络延迟
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(getName() + "卖了第" + ticket-- + "张票");
        }
    }
}
//方式二:声明实现 Runnable 接口的类
public class Test {
    public static void main(String[] args) {
        //创建一个Runnable子类对象
        SellTicket myRunnable = new SellTicket();
        //创建多个线程并起名
        Thread t1 = new Thread(myRunnable, "一号窗口");
        Thread t2 = new Thread(myRunnable, "二号窗口");
        Thread t3 = new Thread(myRunnable, "三号窗口");
        //启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}
class SellTicket implements Runnable {
    int ticket = 100;//初始有100张票,
    //因为多个线程都是从同一个Runnable子类对象来的,可以共享这个普通成员变量
    @Override
    public void run() {
        while (ticket > 0) {//一直卖票,直到票卖完
            try {//模拟选中票后的网络延迟
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖了第" + ticket-- + "张票");
        }
    }
}

エラーの理由:

チケット-操作はアトミック操作ではありません。値の取得、-1操作の実行、値の再割り当ての3つのステップに分割できるため、スレッドの切り替えによって異なる結果が発生します。チケットのような共有データをロックオブジェクトとして扱うことをお勧めします

おすすめ

転載: blog.csdn.net/qq_43496435/article/details/113991995