传统线程生产者-消费者模式

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

传统线程生产者-消费者模式

大厂面试题:

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

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

CountDownLatch、CyclicBarrier、Semaphore使用过吗?

阻塞队列知道吗?

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

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

死锁编码及定位分析?

1、传统线程生产者-消费者模式是什么?

2、传统生产者-消费者模式代码验证2.0版本

Demo One:判断使用while不会出现虚假唤醒问题

package com.wwl.juc;

 

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

/**

 * 线程操作的共享资源类

 */

class ShareData {

    private int num = 0;

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

 

    // 加法操作+1

    public void increment() {

        lock.lock();

        try {

            while (num != 0) {

                // 生产者线程等待生产

                condition.await();

            }

            // 生产者线程进行生产操作

            num++;

            System.out.println(Thread.currentThread().getName() + "\t" + num);

            // 生产者线程通知唤醒消费者线程

            condition.signalAll();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lock.unlock();

        }

    }

 

    // 减法操作-1

    public void decrement() {

        lock.lock();

        try {

            while (num == 0) {

                // 消费者线程等待消费

                condition.await();

            }

            // 消费者线程进行消费操作

            num--;

            System.out.println(Thread.currentThread().getName() + "\t" + num);

            // 消费者线程通知唤醒生产线程

            condition.signalAll();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lock.unlock();

        }

    }

}

 

/**

 * 面试题目:一个初始值为0的变量,两个线程对其交替操作,一个加1,一个减1,交替循环5次

 * 传统模式的生产者和消费者Demo

 * 1、线程操作资源共享类ShareData

 * 2、线程判断(while)是否执行加减操作

 * 3、线程操作完成之后,需要通知(condition.signalAll())其他线程

 * 4、防止虚假唤醒机制(if和while使用哪个?当然是使用while来判断)

 */

public class ProducerAndConsumerDemo {

    public static void main(String[] args) {

        ShareData shareData = new ShareData();

        // 线程t1进行加法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.increment();

            }

        }, "t1").start();

 

        // 线程t2进行减法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.decrement();

            }

        }, "t2").start();

    }

}

程序执行结果如下:生产者线程和消费者线程交替执行加减操作

Demo Two:判断使用if操作会出现虚假唤醒问题(模拟生产者和消费者线程数要大于2,我这里使用两个生产者线程和两个消费这线程)

package com.wwl.juc;

 

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

/**

 * 线程操作的共享资源类

 */

class ShareData {

    private int num = 0;

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();

 

    // 加法操作+1

    public void increment() {

        lock.lock();

        try {

            if (num != 0) {

                // 生产者线程等待生产

                condition.await();

            }

            // 生产者线程进行生产操作

            num++;

            System.out.println(Thread.currentThread().getName() + "\t" + num);

            // 生产者线程通知唤醒消费者线程

            condition.signalAll();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lock.unlock();

        }

    }

 

    // 减法操作-1

    public void decrement() {

        lock.lock();

        try {

            if (num == 0) {

                // 消费者线程等待消费

                condition.await();

            }

            // 消费者线程进行消费操作

            num--;

            System.out.println(Thread.currentThread().getName() + "\t" + num);

            // 消费者线程通知唤醒生产线程

            condition.signalAll();

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lock.unlock();

        }

    }

}

 

/**

 * 面试题目:一个初始值为0的变量,两个线程对其交替操作,一个加1,一个减1,交替循环5次

 * 传统模式的生产者和消费者Demo

 * 1、线程操作资源共享类ShareData

 * 2、线程判断(while)是否执行加减操作

 * 3、线程操作完成之后,需要通知(condition.signalAll())其他线程

 * 4、防止虚假唤醒机制(if和while使用哪个?当然是使用while来判断)

 */

public class ProducerAndConsumerDemo {

    public static void main(String[] args) {

        ShareData shareData = new ShareData();

        // 线程t1进行加法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.increment();

            }

        }, "t1").start();

 

        // 线程t2进行减法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.decrement();

            }

        }, "t2").start();

 

        // 线程t3进行加法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.increment();

            }

        }, "t3").start();

 

        // 线程t4进行减法操作

        new Thread(() -> {

            for (int i = 0; i < 5; i++) {

                shareData.decrement();

            }

        }, "t4").start();

    }

}

程序执行结果如下:生产者线程和消费者线程没有交替执行加减操作

 

 

猜你喜欢

转载自blog.csdn.net/longgeqiaojie304/article/details/91353610
今日推荐