多线程作为java中重量级的知识,几乎在所有的面试中都会被问及,好多小伙伴只知道多线程重要,却不知道,多线程在什么情况下会发生,以及发生了需要怎样去解决,下面案例通过12306抢购最后一张票来展示多线程并发会导致的结果,以及怎样简单的去处理多线程引发的资源抢夺问题!
代码如下:
public class Test {
public static void main(String[] args) {
//某列次车剩余票数
Account myAccount = new Account(1, "列次A车");
//用户A开始抢票!
Drawing you = new Drawing(myAccount, 1, "你");
//用户B开始抢票!
Drawing yourWife = new Drawing(myAccount, 1, "你老婆");
you.start();
yourWife.start();
}
}
//某列次车
class Account {
int ps;//剩余票数
String name;//卡名
public Account(int ps, String name) {
this.ps = ps;
this.name = name;
}
}
//12306:模拟抢票
class Drawing extends Thread {
Account account;//某列次车
int drawingPs;//取了多少张票
int nowPs;//现在手里有多少张票
public Drawing(Account account, int drawingPs,String name) {
super(name);
this.account = account;
this.drawingPs = drawingPs;
}
//synchronized默认锁的this.即Drawing
@Override
public void run() {
//锁的对象是变化的量,需要增删改的对象
// synchronized (account) {
//判断余额是否充足
if (drawingPs > account.ps) {
System.out.println(Thread.currentThread().getName() + ":剩余票数不足!");
return;
}
//模拟延时 sleep可以放大问题的发生性
try {
this.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//余票 = 总票 - 取完的票
account.ps = account.ps - drawingPs;
System.out.println(account.name + "余票为" + account.ps);
nowPs = nowPs + drawingPs;
System.out.println(this.getName() + ":手里的票" + nowPs);
//}
}
}
上面代码中存在两个分线程和一个主线程同时执行,在没有经过任何多线程资源抢夺处理的情况下,打印结果如下:
通过结果可以看出,尽管该列次的车票只剩了1张,但是线程A和线程B还是都买到了票,而该列次剩余的票却显示为-1张,这是不正常的,为了解决以上的问题我们可以将代码中的synchronized 锁定的资源代码来进行释放解决以上出现的问题
释放完这两行代码之后,在执行程序发现不会再发生该列次车的剩余票数为负数的情况
上面是通过synchronized 来简单解决多线程资源抢夺的问题,金三银四,希望对你的面试有所帮助,加油,小伙伴们!