java 电影票售卖系统_Java多线程,实现卖电影票的业务

  • Post author:
  • Post category:java


本篇重点:多线程共享资源时发生的互斥问题

一般的我们售卖电影票或者火车票时会有多个窗口同时买票,

我们来看测试代码:主方法new一个Ticket(一个堆),之后三个线程来启动(三个窗口买票)

class Ticket implements Runnable{

private static int ticket=10;

@Override

public void run() {

for(int i=1;i<=100;i++){

System.out.println(Thread.currentThread().getName()+” – 开始买票”);

synchronized(this){ //同步代码块+对象锁

System.out.println(Thread.currentThread().getName()+” – 买了第”+ticket+”张票”);

ticket–;

}

System.out.println(Thread.currentThread().getName()+” – 结束买票”);

if(ticket<=0){break;}

}

}

}

public class Demo {

public static void main(String[] args) {

Ticket ticket=new Ticket();

new Thread(ticket,”1号窗口”).start();

new Thread(ticket,”2号窗口”).start();

new Thread(ticket,”3号窗口”).start();

}

}

同步块内的代码是原子性的,在没有执行完所有语句时是不会出让CPU的。

在分析以上代码前,我们先简化模型。

class Ticket implements Runnable{

@Override

public void run() {

for(int i=1;i<=5;i++){

System.out.println(Thread.currentThread().getName()+” – A”);

System.out.println(Thread.currentThread().getName()+” – B”);

System.out.println(Thread.currentThread().getName()+” – C”);

}

}

}

public class Demo {

public static void main(String[] args) {

Ticket ticket=new Ticket();

new Thread(ticket,”t1″).start();

new Thread(ticket,”t2″).start();

new Thread(ticket,”t3″).start();

}

}

运行如图:

t1 – A

t2 – A

t3 – A

t3 – B

t1 – B

t3 – C

t2 – B

t2 – C

t3 – A

t1 – C

t1 – A

t1 – B

t1 – C

t3 – B

t3 – C

t3 – A

t2 – A

t3 – B

t1 – A

t3 – C

t2 – B

t3 – A

t1 – B

t3 – B

t2 – C

t3 – C

t1 – C

t3 – A

t2 – A

t2 – B

t2 – C

t2 – A

t2 – B

t2 – C

t2 – A

t2 – B

t3 – B

t1 – A

t3 – C

t2 – C

t1 – B

t1 – C

t1 – A

t1 – B

t1 – C

每次运行结果都会不一样,因为轮流抢占CPU不是我们能控制的。

图解分析:

6d2217bf478e4eed668bdaccc24aa1bc.png

由分析我们得出大概是以一条语句作为基本单位来执行,若多条语句需要作为一个原子性的整理,就需要加互斥锁。

原理大致如图:

dab3c4b73d5d34247d9cf9244ea63bc8.png

加锁的这段区域被称为“互斥区”,里面的代码必须整理执行完毕才会释放锁,让其他线程切入进来。

synchronized具有加锁的功能,实现比较简单。

我们再看卖票的代码:

class Ticket implements Runnable{

private static int ticket=10;

@Override

public void run() {

for(int i=1;i<=100;i++){

try {

Thread.sleep(500); //线程休眠500毫秒,以便观察输出

} catch (InterruptedException e) { //需要处理异常

e.printStackTrace();

}

synchronized(this){ //同步代码块+对象锁(this表示对象锁)

if(ticket<=0){break;}

System.out.println(Thread.currentThread().getName()+” 买了第”+ticket+”张票”);

ticket–;

}

}

}

}

public class Demo {

public static void main(String[] args) {

Ticket ticket=new Ticket();

new Thread(ticket,”1号窗口”).start();

new Thread(ticket,”2号窗口”).start();

new Thread(ticket,”3号窗口”).start();

}

}

运行如图:

03b2eb3adb25fe33e120d7378dd53c37.png



版权声明:本文为weixin_34879325原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。