经典笔试题:线程通信(使用重入锁(ReentrantLock)和条件队列(Condition)实现线程间通信)

经典笔试题:

1、自定义容器,提供新增元素(add)和获取元素数量(size)方法。
2、启动两个线程。线程1向容器中新增10个数据。线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止。

package com.gaopeng.programming.test2;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 练习:使用重入锁(ReentrantLock)和条件队列(Condition)
 * 自定义容器,提供新增元素(add)和获取元素数量(size)方法。
 * 启动两个线程。线程1向容器中新增10个数据。线程2监听容器元素数量,当容器元素数量为5时,线程2输出信息并终止。
 */
public class Test04 {

    public static void main(String[] args) {

        final Test03Container myContainer = new Test03Container();
        final Lock lock = new ReentrantLock();
        final Condition producer = lock.newCondition();
        final Condition consumer = lock.newCondition();

        new Thread(new Runnable() {
            @Override
            public void run() {

                lock.lock();

                try {
                    System.out.println(Thread.currentThread().getName() + "获得锁");

                    if (myContainer.size() != 5) {
                        // 进入等待队列,释放锁标记
                        System.out.println(Thread.currentThread().getName() + "释放锁");
                        consumer.await();

                    }

                    System.out.println("size = 5");
                    producer.signalAll();

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        }, "CONSUMER").start();

        new Thread(new Runnable() {
            @Override
            public void run() {

                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + "获得锁");

                    for (int i = 1; i <= 10; i++) {
                        System.out.println("add Object to Container " + i);
                        myContainer.add(new Object());

                        if (myContainer.size() == 5) {

                            consumer.signalAll();

                            // 进入等待队列,释放锁标记
                            System.out.println(Thread.currentThread().getName() + "释放锁");
                            producer.await();

                        }

                        TimeUnit.SECONDS.sleep(1);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }

            }
        }, "PRODUCER").start();

    }
}

class Test04Container {

    List<Object> container = new ArrayList<>();

    public void add(Object o) {
        this.container.add(o);
    }

    public int size() {
        return this.container.size();
    }
}

运行结果如下:

CONSUMER获得锁
CONSUMER释放锁
PRODUCER获得锁
add Object to Container 1
add Object to Container 2
add Object to Container 3
add Object to Container 4
add Object to Container 5
PRODUCER释放锁
size = 5
add Object to Container 6
add Object to Container 7
add Object to Container 8
add Object to Container 9
add Object to Container 10

原文地址:https://www.cnblogs.com/gaopengpy/p/12264599.html

时间: 2024-11-03 03:08:04

经典笔试题:线程通信(使用重入锁(ReentrantLock)和条件队列(Condition)实现线程间通信)的相关文章

Java并发程序设计(12)并发锁之可重入锁ReentrantLock

1.1. 可重入锁ReentrantLock ReentrantLock是java并发库中提供的可重入锁.与synchronized同步块相比,有相似也有不同.相似的地方有: (1)都可以实现多线程之间的同步,避免对共享资源的访问冲突. (2)都是可重入的,即一个已经获取锁的线程可以再次获得同一个锁,synchronized也类似. 不同的地方有: (1)ReentrantLock更灵活,获取锁和释放锁可以在同一个方法中,也可以在不同方法中.synchronized通常用在同一个方法体内. (2

重入锁----ReentrantLock

本节主要从下述四个方面介绍重入锁. 1.什么是重入锁? 2.为什么要引用重入锁? 3.重入锁是怎么实现的? 4.分析java并发包中ReentrantLock. 什么是重入锁 重入锁,支持重进入的锁,表示该锁能够支持一个线程对它重复加锁,即线程在获得锁之后再次获取该锁时不会被阻塞. 为什么要引用重入锁? 以子类重写父类方法为例: Mutix是不支持重入的锁.(代码摘抄自<java并发编程的艺术>) 1 import java.util.concurrent.TimeUnit; 2 import

重入锁 ReentrantLock (转)(学习记录)

重入锁(ReentrantLock)是一种递归无阻塞的同步机制.以前一直认为它是synchronized的简单替代,而且实现机制也不相差太远.不过最近实践过程中发现它们之间还是有着天壤之别. 以下是官方说明:一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大.ReentrantLock 将由最近成功获得锁定,并且还没有释放该锁定的线程所拥有.当锁定没有被另一个线程所拥有时,调用 lock 的线程将成功获取

java多线程---重入锁ReentrantLock

1.定义 重入锁ReentrantLock,支持重入的锁,表示一个线程对资源的重复加锁. 2.底层实现 每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法:成功后,JVM会记下锁的持有线程,并且将计数器置为1:此时其它线程请求该锁,则必须等待:而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增:当线程退出同步代码块时,计数器会递减,如果计数器为0,则释放该锁. 3.使用样例 eg: import java

java 可重入锁ReentrantLock的介绍

一个小例子帮助理解 话说从前有一个村子,在这个村子中有一口水井,家家户户都需要到这口井里打水喝.由于井水有限,大家只能依次打水.为了实现家家有水喝,户户有水用的目标,村长绞尽脑汁,最终想出了一个比较合理的方案. 首先,在水井边上安排一个看井人,负责维持秩序. 然后,打水时,以家庭为单位,哪个家庭任何人先到井边,就可以先打水,而且如果一个家庭占到了打水权,其家人这时候过来打水不用排队.而那些没有抢占到打水权的人,一个一个挨着在井边排成一队,先到的排在前面. 最后,打水的人打完水以后就告诉看井人,看

JAVA多线程重入锁ReentrantLock应用

package concurrent; import java.util.concurrent.*; import java.util.concurrent.locks.ReentrantLock; /** * @Auther:zhl * @Date:2019/7/13 * @Description: 并发测试,重入锁ReentrantLock解决并发问题 */ public class ConcurrentSample { //并发线程数量 private static int users =

Java 重入锁 ReentrantLock 原理分析

1.简介 可重入锁ReentrantLock自 JDK 1.5 被引入,功能上与synchronized关键字类似.所谓的可重入是指,线程可对同一把锁进行重复加锁,而不会被阻塞住,这样可避免死锁的产生.ReentrantLock 的主要功能和 synchronized 关键字一致,均是用于多线程的同步.但除此之外,ReentrantLock 在功能上比 synchronized 更为丰富.比如 ReentrantLock 在加锁期间,可响应中断,可设置超时等. ReentrantLock 是我们

Java并发(九):重入锁 ReentrantLock

一.ReentrantLock类结构 public class ReentrantLock implements Lock, java.io.Serializable { private final Sync sync; // 锁 大部分功能都是委托给Sync来实现的 abstract static class Sync extends AbstractQueuedSynchronizer {} static final class FairSync extends Sync {} static

Java 重入锁 ReentrantLock

本篇博客是转过来的. 但是略有改动感谢 http://my.oschina.net/noahxiao/blog/101558 摘要 从使用场景的角度出发来介绍对ReentrantLock的使用,相对来说容易理解一些. 场景1:如果发现该操作已经在执行中则不再执行(有状态执行) a.用在定时任务时,如果任务执行时间可能超过下次计划执行时间,确保该有状态任务只有一个正在执行,忽略重复触发. b.用在界面交互时点击执行较长时间请求操作时,防止多次点击导致后台重复执行(忽略重复触发). 以上两种情况多用