多线程经典案例

目录

1、生产者消费者模式

2、抢红包问题


1、生产者消费者模式

这是多线程同步的经典问题,消费者和生产者同时使用一块缓冲区,消费者需要从缓冲区取东西,同时生产者要生产商品放入缓冲区。缓冲区满时生产者不再生产商品,缓冲区为空时消费者也不能再消费。

生产者和消费者共享同一个资源,并且生产者和消费者之间相互依赖,互为条件。

如下图所示:

分析: 

1、设计一个库存类:Store ,push(放入),pop(取出);

2、生产者:调用 push(放入) 多次调用

3、消费者:调用pop(取),多次调用

4、创建多个线程分别模拟生产和消费

库存类:

public class Stock {
    private int count=0;//先设置库存为0;
    //生产者生产的方法,synchronized锁,让线程同步
    public synchronized void push(){
        //设仓库的内存为10
        if(count<10){
            //唤醒所有等待线程
            this.notifyAll();
            System.out.println(Thread.currentThread().getName()+"生产者在生产,库存:"+count++);
            try {
                //睡眠100ms,假设生产的时间
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }else {
            System.out.println(Thread.currentThread().getName()+"仓库满了,库存:"+count);
            try {
                //仓库满了,用wait()方法,线程等待释放锁
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public synchronized void pop(){
        //库存大于0时消费者才能消费
        if(count>0){
            //唤醒所有等待线程
            this.notifyAll();
            System.out.println(Thread.currentThread().getName()+"消费者在消费,库存:"+count--);
            try {
                //睡眠100ms,假设消费的时间
                Thread.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }else {
            System.out.println(Thread.currentThread().getName()+"库存为0不能消费"+count);
            try {
                //仓库空了不能消费,用wait()方法,线程等待释放锁
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

生产者类:

public class Producer extends Thread{
    private Stock stock;//设置一个Stock类型属性的stock
    //构造方法
    public Producer(Stock stock) {
        this.stock = stock;
    }
    //重写run()方法

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            stock.push();
        }
    }
}

消费者类:

public class Consumer extends Thread{//继承Thread类
    private Stock stock;//设置一个Stock类型属性的stock
    //构造方法
    public Consumer(Stock stock) {
        this.stock = stock;
    }
    //重写run()方法
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            stock.pop();
        }
    }
}

测试类:

public class test {
    public static void main(String[] args) {
        //新建一个Stock对象
        Stock stock=new Stock();
        Producer p1=new Producer(stock);
        Producer p2=new Producer(stock);
        Consumer c1=new Consumer(stock);
        Consumer c2=new Consumer(stock);
        p1.start();
        p2.start();
        c1.start();
        c2.start();
    }
}

测试结果:

生产消费者用阻塞队列实现:

public class test01 {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue=new ArrayBlockingQueue<>(10);
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    try {
                        queue.put(i);//添加元素,容量满后 会阻塞
                        System.out.println("生产");
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                }
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    try {
                        int value=queue.take();//移除元素,容量为空后,会阻塞
                        Thread.sleep(200);
                        System.out.println("消费"+value);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();
    }
}

结果:

2、抢红包问题

1、HongBao类

public class HongBao {
    private int money;
    private int num;

    public HongBao(int money, int num) {
        this.money = money;
        this.num = num;
    }
    public synchronized int getRedPacket(){
        if(num==0){
            return 0;
        }
        if(num==1){
            num--;
            return money;
        }
        Random random=new Random();
        int amount =random.nextInt(money/num*2-1)+1;
        money-=amount;
        return num--;
    }

}

2、HongBaoThtead类

public class HongBaoTHread implements Runnable{
    private HongBao hongBao;

    public HongBaoTHread(HongBao hongBao) {
        this.hongBao=hongBao;
    }

    @Override
    public void run() {
        int amount=hongBao.getRedPacket();
        if(amount>0){
            System.out.println(Thread.currentThread().getName()+"抢到了"+amount);
        }else {
            System.out.println(Thread.currentThread().getName()+"没有抢到");
        }
    }
}

3、测试类:

public class Test01 {
    public static void main(String[] args) {
        HongBao hongBao=new HongBao(200,10);
        for (int i = 1; i < 10; i++) {
            new Thread(new HongBaoTHread(hongBao)).start();
        }
    }
}

结果:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值