• 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不是我们能控制的。

    图解分析:

     

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

    原理大致如图:

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

    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();
    	}
    }
    

      运行如图:

  • 相关阅读:
    mysql数据库题目【杭州多测师】【杭州多测师_王sir】
    python题目:维度为(M,N)求矩阵的转置【杭州多测师】【杭州多测师_王sir】
    python题目【杭州多测师】【杭州多测师_王sir】
    购物车测试点【杭州多测师】【杭州多测师_王sir】
    史上最全软件测试工程师常见的面试题总结【杭州多测师】【面试题】【杭州多测师_王sir】
    查询"001"课程比"002"课程成绩高的所有学生的学号【杭州多测师】【杭州多测师_王sir】
    mysql数据库查询当天,最近7天,最近1个月数据【杭州多测师】【杭州多测师_王sir】
    python题目:判断一个IP地址是否合法【杭州多测师】【杭州多测师_王sir】
    sql floor()函数
    mysql左连右连
  • 原文地址:https://www.cnblogs.com/mengxinrenyu/p/8095336.html
Copyright © 2020-2023  润新知