线程通信之生产者-消费者的阻塞队列模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/longgeqiaojie304/article/details/91627751

线程通信之生产者-消费者的阻塞队列模式

大厂面试题:

1、请你谈谈对volatile的理解?

2、CAS你知道吗?

3、原子类AtomicInteger的ABA问题谈谈?原子更新引用知道吗?

4、我们都知道ArrayList是线程不安全的,请编码写一个不安全的案例并给出解决方案?

5、公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解?请手写一个自旋锁。

6、CountDownLatch、CyclicBarrier、Semaphore使用过吗?

7、阻塞队列知道吗?

8、线程池用过吗?ThreadPoolExecutor谈谈你的理解?

9、线程池用过吗?生产上你是如何设置合理参数?

10、死锁编码及定位分析?

 

线程通信之生产者-消费者的阻塞队列模式代码验证

package com.wwl.juc;

 

import java.util.concurrent.ArrayBlockingQueue;

import java.util.concurrent.BlockingQueue;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.atomic.AtomicInteger;

 

/**

 * 线程操作资源类

 */

class MyResource {

    // 控制生产者-消费者标志位

    private volatile boolean FLAG = true;

    // 原子类,保证并发过程中线程安全

    private AtomicInteger atomicInteger = new AtomicInteger(1);

    // 阻塞队列,用作消息队列

    private BlockingQueue<String> blockingQueue;

 

    public MyResource(BlockingQueue<String> blockingQueue) {

        this.blockingQueue = blockingQueue;

        System.out.println("使用阻塞队列:" + blockingQueue.getClass().getName());

    }

 

    // 生产者方法

    public void produce() throws InterruptedException {

        String data;

        boolean produceFlag;

        while (FLAG) {

            data = atomicInteger.getAndIncrement() + "";

            produceFlag = blockingQueue.offer(data, 2, TimeUnit.SECONDS);

            if (produceFlag) {

                System.out.println(Thread.currentThread().getName() + "\t 生产" + data + "成功");

            } else {

                System.out.println(Thread.currentThread().getName() + "\t 生产" + data + "失败");

            }

            TimeUnit.SECONDS.sleep(1);

        }

        System.out.println(Thread.currentThread().getName() + "\t 线程叫停,produce暂停");

    }

 

    // 消费者方法

    public void consume() throws InterruptedException {

        String consumeFlag;

        while (FLAG) {

            consumeFlag = blockingQueue.poll(2, TimeUnit.SECONDS);

            if (consumeFlag == null || "".equals(consumeFlag)) {

                System.out.println(Thread.currentThread().getName() + "\t 线程叫停,consume暂停");

            } else {

                System.out.println(Thread.currentThread().getName() + "\t 消费" + consumeFlag + "成功");

            }

        }

    }

 

    // 暂停线程方法

    public void stop() {

        this.FLAG = false;

    }

 

}

/**
 * 线程通信之生产者-消费者的阻塞队列模式
 * Volatile/CAS/AtomicInteger/BlockingQueue知识点综合使用
 * Volatile保证线程之间的可见性;
 * CAS比较交换算法,减少线程上下文切换,提高并发效率;
 * AtomicInteger原子类,保证在并发的情况下,线程安全;
 * BlockingQueue用作消息队列,不需要手动编写阻塞、唤醒代码,阻塞队列具有自动阻塞、唤醒功能。
 */

public class ProducerConsumerBlockQueueDemo {

    public static void main(String[] args) throws InterruptedException {

        MyResource myResource = new MyResource(new ArrayBlockingQueue<>(10));

        new Thread(() -> {

            System.out.println("生产者Producer线程启动");

 

            try {

                myResource.produce();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }, "producer").start();

 

        new Thread(() -> {

            System.out.println("消费者Consumer线程启动");

            System.out.println();

            System.out.println();

            try {

                myResource.consume();

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }, "consumer").start();

 

        // 模拟业务执行:让生产者-消费者线程执行5秒

        TimeUnit.SECONDS.sleep(5);

 

        // 暂停生产者-消费者线程

        System.out.println(Thread.currentThread().getName() + "\t 暂停生产者-消费者线程");

        myResource.stop();

 

 

    }

}

程序执行结果如下:

猜你喜欢

转载自blog.csdn.net/longgeqiaojie304/article/details/91627751