多线程实现方式?如何启动多线程?什么情况下会发生线程安全问题?如何解决线程安全问题?
一、实现多线程的几种方式
1、继承Threa类
代码案例如下
任务1
package com.xc.threadDemo; public class Task1 extends Thread{ @Override public void run() { for(int i = 1; i < 10; i++) { System.out.println("i===================================" + i); } } }
任务2
package com.xc.threadDemo; public class Task2 extends Thread{ @Override public void run() { for(int j = 1; j < 10; j++) { System.out.println("j=" + j); } } }
线程执行类
package com.xc.threadDemo; public class Test { public static void main(String[] args) { Task1 task1 = new Task1(); Task2 task2 = new Task2(); //如果调用run方法,程序就会从上至下执行 task1.run(); task2.run(); //只有调用start方法,启动而不是运行线程,两个线程才会同时执行 task1.start(); task2.start(); } }
2、实现Runnable接口
代码案例如下
任务1
package com.xc.threadDemo2; public class Task1 implements Runnable{ @Override public void run() { for(int i = 1; i < 1000; i++) { System.out.println("i===================================" + i); } } }
任务2
package com.xc.threadDemo2; public class Task2 implements Runnable{ @Override public void run() { for(int j = 1; j < 1000; j++) { System.out.println("j=" + j); } } }
线程执行类
package com.xc.threadDemo2; public class Test { public static void main(String[] args) { Runnable task1 = new Task1(); Runnable task2 = new Task2(); Thread thread1 = new Thread(task1); Thread thread2 = new Thread(task2); thread1.start(); thread2.start(); } }
二、如何启动线程
如上面的案例所示
1、如果是继承Thread类,启动线程使用对象调用start方法即可
2、如果是实现Runnable接口,启动线程的方式相对复杂一点,但是这是实际开发中使用最多的方式,因为Java是单继承,一旦继承了Thread类,就无法继承其他类
三、什么情况下会发生线程安全问题
当多个线程访问同一个共享数据时,有可能会出现线程安全问题
例如如下案例(火车票购票系统)
package com.xc.threadDemo3; public class TicketSystem extends Thread{ //售票系统只有200张票 public static int ticketNum = 200; @Override public void run() { try { //模拟一个售票窗口有1000人排队买票 for(int i = 1; i <= 1000; i++) { if(ticketNum > 0) { ticketNum--; System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票"); } //模拟每个人买票之后与下一个人买票之前的时间间隔 Thread.sleep(500); } }catch(Exception e) { System.out.println("抢票失败,请检查您的网络!"); } } }
package com.xc.threadDemo3; public class Test { public static void main(String[] args) { //模拟同时有三个售票窗口,分别有1000人同时在排队买票 TicketSystem ticketSystem1 = new TicketSystem(); TicketSystem ticketSystem2 = new TicketSystem(); TicketSystem ticketSystem3 = new TicketSystem(); ticketSystem1.start(); ticketSystem2.start(); ticketSystem3.start(); } }
执行结果
售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下8张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下8张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下7张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下5张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下5张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下4张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下3张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下3张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下2张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下0张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下0张票
结论:
可以看到同一张票,被卖出去两次,这是不允许出现的情况
四、如何解决线程安全问题
解决方案就是加锁,在关键的地方加锁,就可以解决这样的问题,代码如下
package com.xc.threadDemo3; public class TicketSystem extends Thread{ //售票系统只有200张票 public static int ticketNum = 200; @Override public void run() { try { //模拟一个售票窗口有1000人排队买票 for(int i = 1; i <= 1000; i++) { synchronized (TicketSystem.class) { if(ticketNum > 0) { ticketNum--; System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票"); } //模拟每个人买票之后与下一个人买票之前的时间间隔 Thread.sleep(500); } } }catch(Exception e) { System.out.println("抢票失败,请检查您的网络!"); } } }
执行结果
售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下199张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下198张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下197张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下196张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下195张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下194张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下193张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下192张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下191张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下190张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下189张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下188张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下187张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下186张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下185张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下184张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下183张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下182张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下181张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下180张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下179张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下178张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下177张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下176张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下175张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下174张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下173张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下172张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下171张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下170张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下169张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下168张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下167张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下166张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下165张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下164张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下163张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下162张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下161张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下160张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下159张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下158张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下157张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下156张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下155张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下154张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下153张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下152张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下151张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下150张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下149张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下148张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下147张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下146张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下145张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下144张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下143张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下142张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下141张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下140张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下139张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下138张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下137张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下136张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下135张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下134张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下133张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下132张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下131张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下130张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下129张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下128张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下127张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下126张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下125张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下124张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下123张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下122张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下121张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下120张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下119张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下118张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下117张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下116张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下115张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下114张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下113张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下112张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下111张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下110张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下109张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下108张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下107张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下106张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下105张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下104张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下103张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下102张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下101张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下100张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下99张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下98张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下97张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下96张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下95张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下94张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下93张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下92张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下91张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下90张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下89张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下88张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下87张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下86张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下85张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下84张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下83张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下82张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下81张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下80张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下79张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下78张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下77张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下76张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下75张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下74张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下73张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下72张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下71张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下70张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下69张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下68张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下67张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下66张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下65张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下64张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下63张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下62张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下61张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下60张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下59张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下58张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下57张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下56张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下55张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下54张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下53张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下52张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下51张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下50张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下49张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下48张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下47张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下46张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下45张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下44张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下43张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下42张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下41张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下40张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下39张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下38张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下37张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下36张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下35张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下34张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下33张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下32张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下31张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下30张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下29张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下28张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下27张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下26张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下25张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下24张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下23张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下22张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下21张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下20张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下19张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下18张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下17张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下16张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下15张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下14张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下13张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下12张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下11张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下10张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下9张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下8张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下7张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下6张票 售票窗口:Thread[Thread-0,5,main]通知:恭喜您,成功抢到票,还剩下5张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下4张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下3张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下2张票 售票窗口:Thread[Thread-2,5,main]通知:恭喜您,成功抢到票,还剩下1张票 售票窗口:Thread[Thread-1,5,main]通知:恭喜您,成功抢到票,还剩下0张票
总结
1、为什么同步代码块包裹的部分是
if(ticketNum > 0) { ticketNum--; System.out.println("售票窗口:"+Thread.currentThread()+"通知:恭喜您,成功抢到票,还剩下"+ticketNum+"张票"); } //模拟每个人买票之后与下一个人买票之前的时间间隔 Thread.sleep(500);
其他部分为什么不包裹?
因为没有必要包裹,排队的时候,并不会对共享数据产生影响,随意插队并不会对售票系统的票造成什么干扰,只有多个窗口同时操作一张票的时候,才会产生票数错乱的问题
所以同步代码块包裹的地方,才是关键点所在
打一个形象的比喻:
如果很多人排队小便,所有排队的人,在关键的时候,也就是小便的时候,才需要锁住,也就是其他人不能共享便池,其他不能进来,但是脱裤子和穿裤子的时候,就没偶遇必要占用坑位了,这个时候可以到旁边去进行,所以穿裤子不用加锁
2、为什么会产生数据安全问题,也即是票数错乱的问题?
比如售票系统只剩下最后一张票,窗口1有人在买这张票,然后进入判断你条件:if(ticketNum > 0),发现满足条件,但是当票数还没有执行ticketNum--;操作时,第二个人就开始在窗口2买票,此时他会发现还剩余一张,所以就进行了买票,但实际上第一个人已经买走了,只是票数没有减少而已,这样就会发生数据错乱
补充
什么场景下会用到多线程
1、例如我们一开始学习过的《坦克大战》《飞机大战》等Java游戏程序,我方飞机、敌机、子弹、背景就分别是一个线程,分别对应一个Java类,所以开发这种游戏一定要使用多线程
2、不管是单核处理器,还是多核处理器,都是可以实现多线程,如果是单核处理器,当你执行多个线程时,就会出现卡顿,程序没有响应
3、操作系统指控cpu(硬件)来完成任务执行,使用时间调度器,但是时间无法均匀分配,调度cpu进行多线程执行,一会执行以下任务1,然后执行以下任务2
疑问
Java是站在了巨人的肩膀上,那么多线程底层的代码逻辑是如何实现的?