多线程实现买票问题
实现Runnable接口的方式实现四个线程卖100张火车票的问题
点击查看代码
public class TestTicket {
public static void main(String[] args) {
// 启动四个线程卖票。
TicketThread tt = new TicketThread();//一个线程对象
new Thread(tt).start();//启动四个线程,操作TicketThread类中的 tickets成员变量
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class TicketThread implements Runnable {
// 100张票。
private Integer tickets = 100;//争用资源..
@Override
public void run() {
while (tickets > 0) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (this) {//临界区,当某个线程进入临界区后,其它线程必需等该线程执行完毕后,才有机会进入到该代码块中
if(tickets>0) {//此处判断是为了避免出现负数的情况
System.out.println(Thread.currentThread() + " is saling ticket " + tickets);
tickets--;
}
}
}
}
}
点击查看代码
public class TestTicket2 {
public static void main(String[] args) {
// 启动四个线程卖票。
TicketThread2 t1 = new TicketThread2();
t1.start();
TicketThread2 t2 = new TicketThread2();
t2.start();
TicketThread2 t3 = new TicketThread2();
t3.start();
TicketThread2 t4 = new TicketThread2();
t4.start();
}
}
class TicketThread2 extends Thread {
private static Integer tickets = 100;//静态的变量隶属于类,不属于对象,多个对象共享的。
@Override
public void run() {
while (tickets > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
/*
this代表当前对象,我们创建了四个TicketThread2类的对象,this分别代码这四个对象;
相当于有四个对象分别上锁和开锁(厕所有四个门),所以不可取;
所以我们得为共享静态变量所属于的类上锁,即:TicketThread类上锁。
*/
synchronized (TicketThread2.class) {
if(tickets>0) {//此片判断是为了避免出现负数的情况
System.out.println(Thread.currentThread() + "卖出了第" + tickets + "张票");
tickets--;
}
}
}
}
}
点击查看代码
public class TestTicket3 {
public static void main(String[] args) {
Ticket ticket = new Ticket();
ticket.tickets = 150;
// 启动四个线程卖票。
TicketThread3 t1 = new TicketThread3(ticket);
t1.start();
TicketThread3 t2 = new TicketThread3(ticket);
t2.start();
TicketThread3 t3 = new TicketThread3(ticket);
t3.start();
TicketThread3 t4 = new TicketThread3(ticket);
t4.start();
}
}
//在Thread类中用成员代表火车票或定义静态变量都不合适的情况下,我们可以把火车票单独拿出来,然后传入到线程类中
class Ticket{//代表火车票
int tickets=100;
}
class TicketThread3 extends Thread {
Ticket ticket;
public TicketThread3(Ticket ticket){
this.ticket = ticket;
}
@Override
public void run() {
while (ticket.tickets > 0) {
synchronized (ticket) {
if(ticket.tickets>0) {//此片判断是为了避免出现负数的情况
System.out.println(Thread.currentThread() + " 已卖 " + ticket.tickets);
ticket.tickets--;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!