1.多线程实现抢票:
票,资源类
public class Ticket {
public Integer num;
public Ticket(Integer num) {
this.num = num;
}
}
线程类具体的处理细节
public class MyThread extends Thread {
private Ticket ticket;
public MyThread(Ticket ticket) {
this.ticket = ticket;
}
@Override
public void run() {
while (true) {
if (ticket.num <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "---:" + ticket.num);
ticket.num = ticket.num - 1;
}
}
}
启动线程
public static void main(String[] args) {
Ticket ticket = new Ticket(100);
MyThread t1 = new MyThread(ticket);
MyThread t2 = new MyThread(ticket);
MyThread t3 = new MyThread(ticket);
t1.start();
t2.start();
t3.start();
}
测试结果:
Thread-0—:100
Thread-2—:100
Thread-1—:100
Thread-2—:98
Thread-0—:99
Thread-2—:96
Thread-1—:97
Thread-2—:94
Thread-2—:92
Thread-2—:91
从打印的结果发现,三个线程都打印了编号为100的数字,导致资源被重复使用,非线程安全。
加锁后:
public void run() {
while (true) {
synchronized (ticket) {
if (ticket.num <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "---:" + ticket.num);
ticket.num = ticket.num - 1;
}
}
}
再次执行:发现结果正常,线程是安全的;
Thread-0—:100
Thread-1—:99
Thread-1—:98
Thread-1—:97
Thread-1—:96
或则使用原子类来实现:
public class ThreadTicket extends Thread {
public static AtomicInteger ticketNum = new AtomicInteger(0);
public ThreadTicket(Integer ticketNum) {
this.ticketNum.set(ticketNum);
}
@Override
public void run() {
while (true) {
if (ticketNum.get() <= 0) {
break;
}
System.out.println(Thread.currentThread().getName() + "---:" + ticketNum.get());
ticketNum.decrementAndGet();//这里必须使用原子类提供的加减方法实现ticketNum的加减(线程安全),
// ticketNum.set(ticketNum.get() - 1);线程不安全
}
}
}