【线程间通信概念】

线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体必用方式之一。当线程存在通信指挥,线程间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务的处理过程中进行有效的把控和监督。

【使用wait和notify的注意点】

1.wait和notify必须配合synchronized关键字使用

2.wait方法释放锁,而notify不会释放锁

【BlockingQueue】

阻塞队列,支持阻塞的机制,阻塞地放入和得到数据。我们来自行实现LinkedBlockingQueue下面的两个简单的方法put()和take()。

[ put ]

把一个Object加到BlockingQueue里,如果BlockingQueue没有空间,则调用此方法的线程被阻塞,直到BlockingQueue里面有空间再继续。

[ take ]

取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入。

【例子】

package com.higgin.part7;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger; public class MyQueue { //1.需要一个承装元素的队列
private LinkedList<Object> list = new LinkedList<>(); //2.计数器
private AtomicInteger count = new AtomicInteger(); //3.队列的上限和下限
private final int maxSize; private final int minSize = ; //4.构造方法
public MyQueue(int size){
this.maxSize = size;
} //5.锁
private final Object lock = new Object(); /**
* 把一个对象obj添加到BlockingQueue中
* 如果BlockingQueue没有空间,则调用此方法的线程被阻断,直到BolckingQueue里面有空间
*/
public void put(Object obj){
synchronized(lock){
while(count.get() == this.maxSize){
try{
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
//1.加入元素
list.add(obj);
//2.累加计数器
count.incrementAndGet();
//3.此时BlockingQueue中已经有元素,可以执行take方法,所以去唤醒take()方法
lock.notify();
System.out.println("新加入的元素为:"+obj);
}
} /**
* 取走BlockingQueue里排在首位的对象
* 若BlockingQueue为空,进入阻塞状态
*/
public Object take(){
Object ret =null;
synchronized(lock){
while(count.get() == this.minSize){
try{
lock.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
//1. 移除排在首位的元素
ret = list.removeFirst();
//2.计数器递减
count.decrementAndGet();
//3.唤醒另外一个线程
lock.notify();
}
return ret;
} public int getSize(){
return this.count.get();
} public static void main(String[] args){
final MyQueue myQueue = new MyQueue();
myQueue.put("AAA");
myQueue.put("BBB");
myQueue.put("CCC");
myQueue.put("DDD");
myQueue.put("EEE");
System.out.println("当前容器的长度:" + myQueue.getSize()); Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
myQueue.put("FFF");
myQueue.put("GGG");
} },"t1");
t1.start(); Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
Object o1 = myQueue.take();
System.out.println("移除的元素为:" + o1);
Object o2 = myQueue.take();
System.out.println("移除的元素为:" + o2);
} },"t2"); try {
TimeUnit.SECONDS.sleep();
} catch (InterruptedException e) {
e.printStackTrace();
} t2.start();
}
}

【运行结果】

16_Queue_利用wait()和notify()编写一个阻塞队列的更多相关文章

  1. 利用ReentrantLock简单实现一个阻塞队列

    借助juc里的ReentrantLock实现一个阻塞队列结构: package demo.concurrent.lock.queue; import java.util.concurrent.lock ...

  2. 用Java如何设计一个阻塞队列,然后说说ArrayBlockingQueue和LinkedBlockingQueue

    前言 用Java如何设计一个阻塞队列,这个问题是在面滴滴的时候被问到的.当时确实没回答好,只是说了用个List,然后消费者再用个死循环一直去监控list的是否有值,有值的话就处理List里面的内容.回 ...

  3. 使用 ReentrantLock 和 Condition 实现一个阻塞队列

    前言 从之前的阻塞队列的源码分析中,我们知道,JDK 中的阻塞队列是使用 ReentrantLock 和 Condition 实现了,我们今天来个简易版的.代码如下: 代码 public class ...

  4. 浅谈Java中的Condition条件队列,手摸手带你实现一个阻塞队列!

    条件队列是什么?可能很多人和我一样答不出来,不过今天终于搞清楚了! 什么是条件队列 条件队列:当某个线程调用了wait方法,或者通过Condition对象调用了await相关方法,线程就会进入阻塞状态 ...

  5. 利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:

    #!/usr/bin/env python3 # -*- coding: utf-8 -*- from functools import reduce CHAR_TO_INT = { ': 0, ': ...

  6. [原创]如何编写多个阻塞队列连接下的多生产者多消费者的Python程序

    平常在写程序时,往往会遇到一个需求:在程序的多个阶段都会出现阻塞的可能,因此,这多个阶段就需要并发执行. Python的多线程有一个特点,就是不允许从外部结束一个运行中的线程,这给我们编写代码时带来了 ...

  7. 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?

    多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...

  8. 0038 Java学习笔记-多线程-传统线程间通信、Condition、阻塞队列、《疯狂Java讲义 第三版》进程间通信示例代码存在的一个问题

    调用同步锁的wait().notify().notifyAll()进行线程通信 看这个经典的存取款问题,要求两个线程存款,两个线程取款,账户里有余额的时候只能取款,没余额的时候只能存款,存取款金额相同 ...

  9. 多线程,线程类三种方式,线程调度,线程同步,死锁,线程间的通信,阻塞队列,wait和sleep区别?

    重难点梳理 知识点梳理 学习目标 1.能够知道什么是进程什么是线程(进程和线程的概述,多进程和多线程的意义) 2.能够掌握线程常见API的使用 3.能够理解什么是线程安全问题 4.能够知道什么是锁 5 ...

随机推荐

  1. SQL中删除重复的行(重复数据),只保留一行 转

    方法一:使用在T-SQL的编程中 分配一个列号码,以COL1,COL2组合来分区排序,删除DATABASE重复的行(重复数据),只保留一行 // COL1,COL2是数据库DATABASE的栏位 de ...

  2. alter table添加表约束

    翻阅了一下网上关于alter table添加表约束的资料,学习下,然后供自己以后使用. 仅仅供自己使用... 总结alter table ### add constraint ## 使用方法 添加表约 ...

  3. javascrip 中排序的函数怎么理解

    其中s是数组[888,2222,9,4]:我不明白sort函数中参数是如何作用的,function中的a和b又是干什么的? 那个function的作用就是比较两个数的大小用的,然后返回结果的正负作为排 ...

  4. POJ_3262 Protecting the Flowers 【贪心】

    一.题面 POJ3262 二.分析 这题要往贪心上面想应该还是很容易的,但问题是要证明为什么比值关系就能满足. 可以选择几个去分析,入1-6  与 2-15  和 1-6 与2-5 和 1-6 与 2 ...

  5. [转] 最简单实现跨域的方法:使用nginx反向代理

    [From] http://blog.jobbole.com/90975/ 什么是跨域 跨域,指的是浏览器不能执行其他网站的脚本.它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全 ...

  6. Oracle Purge和drop的区别

    转自: http://www.cnblogs.com/HondaHsu/archive/2012/09/28/2707487.html 最近发现oracle中出现了这些奇怪的表名,上网查找后发现是or ...

  7. javascript的事件触发和接收源码

    define(function(require,exports,module){ var Events=function(){ var array = []; var push = array.pus ...

  8. aoj0525

    一.题意:题目大致是讲一个烧饼铺烤烧饼,在一个n X m (1<=n<=10,1<=m<=10000)的烤桌上面摆着一堆烧饼,数字1表示烧饼正面,0表示烧饼反面.然后你每次可以 ...

  9. html中的flv视频播放器

    项目中要播放flv视屏,第一时间想到html5的<video>标签,只是很可惜<video>兼容性差也就算了,居然还对格式有明确限制,也就是说只支持Ogg.MPEG4.WebM ...

  10. 一套完整的VI包含哪些元素

    VI设计,即视觉识别系统,企业VI设计是企业品牌建设的重中之重.最近很多人都在问,一套完整的企业VI设计都包括哪些内容?笔者站在一个高级设计师的角度,来简单谈一谈VI设计包括哪些内容.文中指出,一套完 ...