当前位置: 首页 > 后端技术 > Java

抛开Java多线程,我们来看一个现实生活中的例子——阻塞

时间:2023-04-01 18:48:20 Java

售票引起的思考热门景区往往开设多个售票窗口,一个是为了同时接待更大的客流,但是为了防止一台售票机出现故障,没人能买到票。这就引出了多线程中第一个重要的概念,阻塞。其实单核跑多线程不一定比单线程快,因为CPU需要调度和切换线程,为什么要用多线程呢?其实使用多线程技术的一个重要原因是为了防止单个线程被阻塞,导致整个项目无法继续运行。回头看自己项目使用多线程的场景,是不是因为有可能出现组拥堵的情况才使用多线程?如果不存在线程可能阻塞的情况,那么根本就没有必要使用多线程。这是使用多线程阻塞的一个非常重要的先决条件。下面我们用代码来模拟单窗口和多窗口的售票场景://只有一个窗口售票publicclassSimpleStation{privatestaticintticks=20;publicstaticvoidmain(String[]args){while(ticks>0){if(ticks==15){//这里模拟售票机故障thrownewRuntimeException("machinedown...");}刻度线--;System.out.println("售出一张票,还有:"+ticks+"票");}}}运行结果:售出一张,剩余:售出19张,还剩一张:售出18张,还剩一张左边:售出17张,售出一张,左边:售出16张,售出一张,剩余:15张线程异常"main"java.lang.RuntimeException:machinedown...atSimpleStation.main(SimpleStation.java:9)Processfinishedwithexitcode1从上面的运行结果可以看出,当票还剩15张时,剩下的因唯一一台售票机出故障,将售出15张票。接下来我们使用多线程来解决这个问题:ticks>0){System.out.println(getName()+"卖票");尝试{睡眠(1000);}catch(InterruptedExceptione){e.printStackTrace();}if(ticks>15&&getName().equals("window1")){//这里模拟窗口1的售票机失败thrownewRuntimeException(getName()+"Failed");}synchronized(obj){if(ticks>0){//这里totalTick是受限的共享资源ticks--;System.out.println(getName()+"售出1票,剩余:"+totalTick+"票数");}else{系统。out.println(getName()+"今天的票已售罄");}}}}}publicclassMainClass{publicstaticvoidmain(String[]args){Stationstation1=newStation("window1");Stationstation2=newStation("window2");Stationstation3=newStation("window3");station2.start();站1。开始();station3.start();}}运行结果:window2售票1张,window3售票,window1售票,window3售票,剩余:window3售票19张,window2售票,left:window2售票18张线程“window1”中的异常java.lang.RuntimeException:window1failedatStation.run(MainClass.java:21)window3sold1ticket,remaining:17Ticketwindow3sold1window2ticket,remaining:16ticketswindow2soldwindow3ticket1ticket,remaining:15票window3售出1window2票,remaining:14window2售出的票中,window3售出1张,剩余:window3售出13张,window2售出1张,剩余:window2售出12张,window3售出1张,剩余:window3售出11张,window2售出1张,剩余:window2售出10张,window2售出1张window3售出,剩余:window3售出9张,window2售出1张,剩余:window2售出8张,window3售出1张,剩余:7张售出window3,window2售出1张,剩余:window2售出6张,window3售出1张。剩余:窗口3售出5张,窗口2售出1张,剩余:窗口2售出4张,窗口3售出1张,剩余:窗口3售出3张,窗口2售出1张,剩余:2票window2售出1window3票,剩余:1票window3售出1window2票,剩余:0票window3今天的票我们可以看到,虽然1号窗口的机器出现故障,但是并没有影响到2号窗口和3号窗口,继续售票。这就是多线程的魅力!还是基于上面卖票的例子,如果景区每天接待总人数达到一定值,就不再接待游客,所以每个售票窗口都需要正确更新剩余门票总数每张票都卖了。那么这个时候你会思考一个问题。如果还剩15张票,两个窗口看到的剩余票数是15张,两个窗口同时卖一张票,然后几乎同时卖掉剩下的票。金额刷新为14,此时保证金没有实际反应。我们可以让卖票的动作同步进行,但是一定要保证更新保证金的动作能够一个一个的进行。这就引出了多线程的第二个重要概念——资源共享与竞争。在这个例子中,共享的竞争资源是票。如何保证同一时间只有一个线程写入票数,这就是我们下面要讲的,通过synchronized。详情请看下一篇文章。