仮定映画館で映画を見せている、と映画が持つ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つのステップに分割できるため、スレッドの切り替えによって異なる結果が発生します。チケットのような共有データをロックオブジェクトとして扱うことをお勧めします