Java Multithreading Tutorial: Simulating Ticket Booking with Runnable
This article explains how to implement Java multithreading using the Runnable interface through a ticket‑booking example, demonstrates common pitfalls like calling run() directly, shows code with and without Thread.sleep, and discusses concurrency issues such as thread‑unsafe ticket duplication.
Previously we discussed Java multithreading approaches, noting that extending Thread or implementing Runnable are possible, but implementing Runnable is generally preferred.
A common mistake is invoking the run() method directly; the correct way to start a new thread is to call start().
To illustrate multithreading, we analyze a ticket‑booking scenario where a limited number of train seats are available and multiple users attempt to purchase tickets simultaneously.
Define the total number of tickets (e.g., 10) and ensure the number of sold tickets never exceeds this limit.
Maintain the remaining ticket count, which must stay non‑negative.
Allow N users to compete for tickets concurrently using multiple threads and display the results.
package demo11;
//买火车票的例子
public class TestThread4 implements Runnable {
//火车票票数
private int ticketNums = 10;
//重写run方法
@Override
public void run() {
while (true) {
if (ticketNums <= 0) {
break;
}
//打印出谁拿到了第N张票 谁用的是 Thread.currentThread().getName
System.out.println(Thread.currentThread().getName() + "-->拿到了第 " + ticketNums-- + " 张票");
}
}
public static void main(String[] args) {
TestThread4 ticket = new TestThread4();
//目前有三个线程在抢10张票
new Thread(ticket, "小明").start();
new Thread(ticket, "老师").start();
new Thread(ticket, "黄牛党").start();
}
}Running this program with three threads ("小明", "老师", "黄牛党") shows that the first two obtain tickets while the third may miss out, illustrating basic thread scheduling.
小明-->拿到了第 10 张票
小明-->拿到了第 8 张票
小明-->拿到了第 7 张票
老师-->拿到了第 9 张票
小明-->拿到了第 6 张票
老师-->拿到了第 5 张票
老师-->拿到了第 3 张票
小明-->拿到了第 4 张票
老师-->拿到了第 2 张票
小明-->拿到了第 1 张票A second execution may let the "黄牛党" thread also acquire tickets, demonstrating that thread execution order is nondeterministic.
小明-->拿到了第 10 张票
老师-->拿到了第 9 张票
黄牛党-->拿到了第 7 张票
小明-->拿到了第 8 张票
黄牛党-->拿到了第 5 张票
黄牛党-->拿到了第 4 张票
黄牛党-->拿到了第 3 张票
老师-->拿到了第 6 张票
黄牛党-->拿到了第 1 张票
小明-->拿到了第 2 张票To slow down the output and observe thread behavior, we can insert Thread.sleep(1000) inside the loop, handling the required InterruptedException with a try‑catch block.
package demo11;
//买火车票的例子
public class TestThread4 implements Runnable {
//火车票票数
private int ticketNums = 10;
//重写run方法
@Override
public void run() {
while (true) {
if (ticketNums <= 0) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印出谁拿到了第N张票 谁用的是 Thread.currentThread().getName
System.out.println(Thread.currentThread().getName() + "-->拿到了第 " + ticketNums-- + " 张票");
}
}
public static void main(String[] args) {
TestThread4 ticket = new TestThread4();
//目前有三个线程在抢10张票
new Thread(ticket, "小明").start();
new Thread(ticket, "老师").start();
new Thread(ticket, "黄牛党").start();
}
}Running the version with Thread.sleep shows a one‑second pause after each ticket is printed, and also reveals that without proper synchronization the same ticket number can be printed by multiple threads, indicating a thread‑unsafe (data race) situation.
How to resolve such concurrency issues will be covered in a future article.
「Have Fun ~ Tester !」
140 interview questions (UI, Linux, MySQL, API, Security)
Share 11 written test papers
Fiddler learning package
Microsoft Zune leap‑year bug analysis
Phone‑binding performance test
Automated testing lifecycle
Quality over quantity in software testing
Web security checklist
Code‑based vs. no‑code automation
Python Socket.IO testing script
Thread‑pool batch API request practice
Golang fasthttp practice
Colored console output
Automa basic features demo
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.