教你用三种方式模拟两个线程抢票
Java后端技术
共 9682字,需浏览 20分钟
·
2024-06-25 09:19
往期热门文章:
使用 Synchronized 来确保一次只有一个线程可以访问票资源。
使用 ReentrantLock 来实现线程间的协调。
使用 Semaphore 来限制同时访问票的线程数量。
static class TicketSystemBySynchronized {
private int tickets = 100;
public void sellTicket() {
while (tickets > 0) { //还有票时进行循环
synchronized (this) {
try {
if (tickets > 0)
System.out.println(Thread.currentThread().getName()
+ "卖出一张票,剩余票数:" + --tickets);
Thread.sleep(200); //模拟售票
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class TicketSystemByReentrantLock {
private int tickets = 100;
private final ReentrantLock lock = new ReentrantLock(); //定义锁
public void sellTicket() {
while (tickets > 0) {
lock.lock(); //上锁
try {
Thread.sleep(200); //模拟售票
if (tickets > 0)
System.out.println(Thread.currentThread().getName()
+ "卖出一张票,剩余票数:" + --tickets);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //解锁
}
}
}
}
static class TicketSystemBySemaphore {
private final Semaphore semaphore;
public TicketSystemBySemaphore() {
this.semaphore = new Semaphore(100); //总共100张票
}
public void sellTicket() {
int i = semaphore.availablePermits(); //返回此信号量中当前可用的许可证数
while (i > 0) {
try {
Thread.sleep(200);
semaphore.acquire(); // 获取信号量,如果信号量为0,线程将阻塞等待
System.out.println(
Thread.currentThread().getName() + "卖出一张票,剩余票数:" + --i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
semaphore.release(); // 释放信号量,允许其他线程获取信号量
}
}
}
}
public interface TicketSystem {
void sellTicket();
}
static class CodeSandboxFactory {
static TicketSystem newInstance(String type) {
switch (type) {
case "Synchronized":
return new TicketSystemBySynchronized();
case "ReentrantLock":
return new TicketSystemByReentrantLock();
case "Semaphore":
default:
return new TicketSystemBySemaphore();
}
}
}
如果type参数的值为"Synchronized",则返回一个新的 TicketSystemBySynchronized对象;
如果type参数的值为"ReentrantLock",则返回一个新的 TicketSystemByReentrantLock 对象;
如果type参数的值为"Semaphore",则返回一个新的 TicketSystemBySemaphore对象;
如果type参数的值不是以上三种之一,则默认返回一个新的TicketSystemBySemaphore 对象。
public class ThreadsGrabTickets {
public static void main(String[] args) {
TicketSystem system = CodeSandboxFactory.newInstance("Synchronized");
// TicketSystem system =
// CodeSandboxFactory.newInstance("ReentrantLock"); TicketSystem
// system = CodeSandboxFactory.newInstance("Semaphore");
new Thread(system::sellTicket, "线程1").start();
new Thread(system::sellTicket, "线程2").start();
}
static class CodeSandboxFactory {
static TicketSystem newInstance(String type) {
switch (type) {
case "Synchronized":
return new TicketSystemBySynchronized();
case "ReentrantLock":
return new TicketSystemByReentrantLock();
case "Semaphore":
default:
return new TicketSystemBySemaphore();
}
}
}
static class TicketSystemBySynchronized implements TicketSystem {
private int tickets = 100;
public void sellTicket() {
while (tickets > 0) {
synchronized (this) {
try {
if (tickets > 0)
System.out.println(Thread.currentThread().getName()
+ "卖出一张票,剩余票数:" + --tickets);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class TicketSystemByReentrantLock implements TicketSystem {
private int tickets = 100;
private final ReentrantLock lock = new ReentrantLock(); //定义锁
public void sellTicket() {
while (tickets > 0) {
lock.lock(); //上锁
try {
Thread.sleep(200); //模拟售票
if (tickets > 0)
System.out.println(Thread.currentThread().getName()
+ "卖出一张票,剩余票数:" + --tickets);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock(); //解锁
}
}
}
}
static class TicketSystemBySemaphore implements TicketSystem {
private final Semaphore semaphore;
public TicketSystemBySemaphore() {
this.semaphore = new Semaphore(100); //总共100张票
}
public void sellTicket() {
int i = semaphore.availablePermits(); //返回此信号量中当前可用的许可证数
while (i > 0) {
try {
Thread.sleep(200);
semaphore.acquire(); // 获取信号量,如果信号量为0,线程将阻塞等待
System.out.println(Thread.currentThread().getName()
+ "卖出一张票,剩余票数:" + --i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
semaphore.release(); // 释放信号量,允许其他线程获取信号量
}
}
}
}
}
转自:绿皮龟,
链接:blog.csdn.net/kologin/article/details/135953580
往期热门文章:
1、听说你还在用Xshell? 2、惊艳到我的 10个 MySQL高级查询技巧! 3、我有点想用JDK17了 4、解放大脑:ChatGPT + PlantUML = 不用画图了 5、高逼格的SQL写法:行行比较 6、限流算法哪家强?时间窗口,令牌桶与漏桶算法对比 7、每天都提交代码,那你知道.git目录内部的秘密吗? 8、我患上了空指针后遗症 9、这10个小技巧让你减少80%的Bug! 10、升级 JDK17 一个不可拒绝的理由
评论