业务描述 假设有200张票,用4个线程去订票,不能有两个或者以上的线程订到了 同一个票(原因就不说了),当最后一张票卖掉的时候结束,再订就抛 异常提示出票卖完了。 业务分析,要实现以上功能, 1、需要创建一个车票类,初始化票,卖票的接口saleTicket() 2、自定义异常的一个类。 3、创建卖票线程类,在run方法中卖车票。 4、初始化车票的线程,负责初始化车票,也就是初始化Ticket类中的数组。 5、创建主方法进行测试。
时间: 2024-02-23 07:59:40 浏览: 30
好的,这是一个经典的多线程编程问题,需要采用同步机制来保证线程安全。下面是一种可能的实现方式:
1. 首先定义一个车票类,包含票号和是否已售出的标志:
```java
public class Ticket {
private int id; // 票号
private boolean sold; // 是否已售出
public Ticket(int id) {
this.id = id;
this.sold = false;
}
public int getId() {
return id;
}
public synchronized boolean isSold() {
return sold;
}
public synchronized void sell() {
sold = true;
}
}
```
2. 自定义一个票已售完的异常类:
```java
public class TicketSoldOutException extends Exception {
public TicketSoldOutException() {
super("Ticket sold out");
}
}
```
3. 创建一个卖票线程类,每个线程从共享的票池中尝试获取未售出的票进行售卖,如果所有票都已售出则抛出自定义异常:
```java
public class SalesThread extends Thread {
private final List<Ticket> tickets;
private final int id;
private final Object lock;
public SalesThread(List<Ticket> tickets, int id, Object lock) {
this.tickets = tickets;
this.id = id;
this.lock = lock;
}
@Override
public void run() {
while (true) {
synchronized (lock) {
if (tickets.isEmpty()) {
System.out.println("Thread " + id + " exits.");
return;
}
Ticket ticket = null;
for (Ticket t : tickets) {
if (!t.isSold()) {
ticket = t;
break;
}
}
if (ticket == null) {
System.out.println("Thread " + id + " exits.");
return;
}
ticket.sell();
System.out.println("Thread " + id + " sold ticket " + ticket.getId());
}
}
}
}
```
4. 初始化车票的线程,负责初始化票池:
```java
public class TicketInitializer extends Thread {
private final List<Ticket> tickets;
private final Object lock;
public TicketInitializer(List<Ticket> tickets, Object lock) {
this.tickets = tickets;
this.lock = lock;
}
@Override
public void run() {
for (int i = 1; i <= 200; i++) {
tickets.add(new Ticket(i));
}
synchronized (lock) {
lock.notifyAll();
}
}
}
```
5. 创建主方法进行测试,首先创建共享的票池和同步锁,然后启动初始化线程初始化票池,最后启动4个卖票线程进行售卖:
```java
public class Main {
public static void main(String[] args) throws InterruptedException {
List<Ticket> tickets = new ArrayList<>();
Object lock = new Object();
TicketInitializer initializer = new TicketInitializer(tickets, lock);
initializer.start();
synchronized (lock) {
while (tickets.isEmpty()) {
lock.wait();
}
}
SalesThread[] threads = new SalesThread[4];
for (int i = 0; i < threads.length; i++) {
threads[i] = new SalesThread(tickets, i + 1, lock);
threads[i].start();
}
for (SalesThread t : threads) {
t.join();
}
System.out.println("All tickets sold out.");
}
}
```
这样就完成了一个简单的多线程订票系统,在多线程的环境下保证了线程安全。
相关推荐
![java](https://img-home.csdnimg.cn/images/20210720083646.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)