线程案例(线程同步)

目录

案例:卖票

卖票案例数据安全问题的解决

同步代码块

同步方法


案例:卖票

需求:某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

思路:

1、定义一个类SellTicket实现Runnable接口,里面定义一个成员变量:privateinttickets=100

2、在SellTicket类中重写run)方法实现卖票,代码步骤如下
        A:判断票数大于0,就卖票,并告知是哪个窗口卖的

        B:卖了票之后,总票数要减1
        C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行

3、定义一个测试类SellTicketDemo,里面有main方法,代码步骤如下
        A:创建SellTicket类的对象
        B:创建三个Thread类的对象,把SellTicket对象作为构造方法的参数,并给出对应的窗口名称

        C:启动线程

package zyy04;

public class Sell implements Runnable{
    private int tickets=10;

    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}
package zyy04;

public class Demo {
    public static void main(String[] args) {
        Sell s=new Sell();
        Thread t1=new Thread(s,"窗口1");
        Thread t2=new Thread(s,"窗口2");
        Thread t3=new Thread(s,"窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

卖票案例的思考

刚才讲解了电影院卖票程序,好像没有什么问题。但是在实际生活中,售票时出票也是需要时间的所以,在出售一张票的时候,需要一点时间的延迟,接下来我们去修改卖票程序中卖票的动作:每次出票时间100毫秒,用sleep0方法实现

package zyy04;

public class Sell implements Runnable{
    private int tickets=10;

    @Override
    public void run() {
        while (true) {
            if (tickets > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
                tickets--;
            }
        }
    }
}

卖票出现了问题
相同的票出现了多次出现了负数的票

问题原因:
线程执行的随机性导致的

卖票案例数据安全问题的解决

为什么出现问题?(这也是我们判断多线程程序是否会有数据安全问题的标准)
        是否是多线程环境

        是否有共享数据
        是否有多条语句操作共享数据

如何解决多线程安全问题呢?
        基本思想:让程序没有安全问题的环境

怎么实现呢?
        把多条语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可

        Java提供了同步代码块的方式来解决

同步代码块

锁多条语句操作共享数据,可以使用同步代码块实现
        格式:
        synchronized(任意对象){
        多条语句操作共享数据的代码}

        synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁

同步的好处和弊端:
        好处:解决了多线程的数据安全问题
        弊端:当线程很多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

package zyy04;

public class Sell implements Runnable{
    private int tickets=10;
    private Object obj=new Object();
    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + tickets + "张票");
                    tickets--;
                }
            }
        }
    }
}

同步方法

同步方法:就是把synchronized关键字加到方法上

        格式:
        修饰符synchronized返回值类型方法名(方法参数){}

同步方法的锁对象是什么呢?
        This

同步静态方法:就是把synchronized关键字加到静态方法上
        格式:
        修饰符staticsynchronized返回值类型方法名(方法参数){}

同步静态方法的锁对象是什么呢?
        类名.class

猜你喜欢

转载自blog.csdn.net/qq_62799214/article/details/127154868