使用多线程,模拟三个窗口同时售票 100 张
代码
存在超卖现象,即线程不安全
package program;
/**
* @Author 雾潋
* @Version 1.0
* 使用多线程,模拟三个窗口同时售票 100 张
*/
@SuppressWarnings("all")
public class SellTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread = new Thread(ticket);
thread.start();//线程一
Ticket ticket1 = new Ticket();
Thread thread1 = new Thread(ticket1);
thread1.start();//线程二
Ticket ticket2 = new Ticket();
Thread thread2 = new Thread(ticket2);
thread2.start();//线程三
/*//方式二
Ticket2 ticket21 = new Ticket2();
ticket21.start();
Ticket2 ticket22 = new Ticket2();
ticket22.start();
Ticket2 ticket23 = new Ticket2();
ticket23.start();*/
}
}
//方法一
class Ticket implements Runnable{
public static int tickets = 100;
@Override
public void run() {
while (true){
if (tickets <= 0) {
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + ",剩余票数:" + (--tickets));
}
}
}
//方式二
class Ticket2 extends Thread {
public static int tickets = 100;
@Override
public void run() {
while (true){
if (tickets <= 0) {
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + ",剩余票数:" + (--tickets));
}
}
}
结果
改进
使用sychronied实现同步,即线程安全
package program;
/**
* @Author 雾潋
* @Version 1.0
* 使用多线程,模拟三个窗口同时售票 100 张
*/
@SuppressWarnings("all")
public class SellTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
Thread thread = new Thread(ticket);
thread.start();//线程一
Ticket ticket1 = new Ticket();
Thread thread1 = new Thread(ticket1);
thread1.start();//线程二
ticket1.setLoop(false);
Ticket ticket2 = new Ticket();
Thread thread2 = new Thread(ticket2);
thread2.start();//线程三
/*//方式二
Ticket2 ticket21 = new Ticket2();
ticket21.start();
Ticket2 ticket22 = new Ticket2();
ticket22.start();
Ticket2 ticket23 = new Ticket2();
ticket23.start();*/
}
}
//方法一
class Ticket implements Runnable{
public static int tickets = 100;
private boolean loop = true; //用于主线程控制子线程退出
public synchronized void f() { //同步方法,在同一时刻,只有一个线程来执行run方法
if (tickets <= 0) {
System.out.println("售票结束");
loop = false;
return;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + ",剩余票数:" + (--tickets));
}
@Override
public void run() {
while (loop){
f();
}
}
public boolean isLoop() {
return loop;
}
public void setLoop(boolean loop) {
this.loop = loop;
}
}
//方式二 未更改,依旧会超票
class Ticket2 extends Thread {
public static int tickets = 100;
@Override
public void run() {
while (true){
if (tickets <= 0) {
System.out.println("售票结束");
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + ",剩余票数:" + (--tickets));
}
}
}
结果
有多个售票结束是因为仍然有子线程进入f()方法,但是由于判断票数为0,故输出收票结束