java多线程实现抢票的案例

本文详细介绍了在Java中创建多线程的三种方式,包括继承Thread类、实现Runnable接口以及通过Lambda表达式。并通过一个售票系统的案例,深入探讨了线程安全问题及其解决方案,如使用同步代码块和同步方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、首先说一下怎么创建多线程的方式

1、创建一个类 继承 Thread 类,重写 run() 方法。

public class MyThread extends Thread{
		    @Override
		    public void run() {
		        System.out.println("创建线程");
		    }
		}

2、创建一个类 实现 Runnable 接口,实现 run() 方法。

public class MyThread implements Runnable{
		    @Override
		    public void run() {
		        System.out.println("创建线程");
		    }
		}

3、同时开启多个线程,并调用该方法。

创建新的线程对象,调用该线程的start()方法,如果调用run()方法,线程的名称都是 main

(1)当使用继承时:

class Test {
    public static void main(String[] args) {
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
    }
}

方法
输出的结果
(2)当使用Runnable时:

在创建实现Runnable接口的对象时,只能创建一个,然后new Thread对象调用start方法启动线程。结果跟之前一样,就不贴出来了。

二、经过基本的了解,下面开始售票的案例:

需求:100张票,三个窗口同时出售,不能出现重票情况。

public class MyThread implements Runnable{

    private static int ticket = 100;

    @Override
    public void run() {
        while (true){
            if(ticket>0){
                System.out.println(Thread.currentThread().getName()+"-------"+ticket);
                ticket--;
            }else{
                break;
            }
        }
    }
}
class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        new Thread(myThread).start();
        new Thread(myThread).start();
        new Thread(myThread).start();
    }
}

输出的结果是:

在这里出现了重复卖出 第100 号票,所以出现了线程安全问题。

解决线程安全问题(利用线程同步的机制)

(1)使用同步代码块
在这里插入图片描述

private Object obj = new Object();//这个是 锁,任意对象,但是 对象必须唯一
synchronized (obj){
    // 这一块是需要操作的共享数据
}

在继承Thread的对象里需要将 obj 静态化,因为调用new Thread().start()方法时,是创建新的对象,不符合锁的要求。所以需要使用 静态的:

private static Object obj = new Object();

(2)使用同步方法:方法的内部操作共享数据,在方法的权限修饰词后面加一个 synchronized 关键字就行了

实现接口的方式:

public class MyThread implements Runnable{

    private static int ticket = 100;
    @Override
    public void run() {
        while (ticket>0){
            show();
        }
    }

    private synchronized void show(){
        if(ticket>0){
            System.out.println(Thread.currentThread().getName()+"+++++++++"+ticket);
            ticket--;
        }

    }
}

class Test {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        new Thread(myThread).start();
        new Thread(myThread).start();
        new Thread(myThread).start();
    }
}

继承的方式:需要在 synchronized 前面加一个 static 关键字

private static synchronized void show(){
        if(ticket>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"+++++++++"+ticket);
            ticket--;
        }
    }
好了,以上就是一个简单的线程安全问题,第一次写,不太会,望各位大佬体谅。有什么问题麻烦提出,我来改正。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值