【线程间通信概念】

线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体必用方式之一。当线程存在通信指挥,线程间的交互性会更强大,在提高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. Centos文章列表

    1.Linux 中将用户添加到组的指令:https://cnzhx.net/blog/linux-add-user-to-group/ 2.CentOS7为firewalld添加开放端口及相关操作:h ...

  2. SqlServer批量插入(SqlBulkCopy、表值参数)

    之前做项目需要用到数据库的批量插入,于是就研究了一下,现在做个总结. 创建了一个用来测试的Student表: CREATE TABLE [dbo].[Student]( [ID] [int] PRIM ...

  3. C#直接使用DllImport外部Dll的方法

    C#.Net调用基本格式:[DLLImport(“DLL文件路径”)]修饰符 extern 返回值类型 方法名称(参数列表) 如: [DllImport("kernel32.dll" ...

  4. iframe里面的元素触发父窗口元素事件的jquery代码 转

    例如父窗口定义了一个事件. top: $(dom1).bind('topEvent', function(){}); 那么iframe里面的元素怎样触发父窗口dom1的事件呢?这样吗? $(dom1, ...

  5. maven No compiler is provided environment

    eclipse maven操作正常出现的No compiler is provided in this environment. Perhaps you are running on a JRE ra ...

  6. WebStorm ES6 语法支持设置和ES6语法的JS文件编译为ES5语法文件

    ECMAScript 6是JavaScript语言的下一代标准,已经在2015年6月正式发布了.Mozilla公司将在这个标准的基础上,推出JavaScript 2.0.ES6的目标,是使得JavaS ...

  7. 【转】Caused by: Action class [com.struts.action.xxxAction] not found 解决方法

    刚学习Struts,自己写了个简单程序,一启动tomcat就报错,但是我按着ctrl点击struts.xml中com.struts.action.LoginAction也能定位到LoginAction ...

  8. Flask 知识点

    flask run时候端口占用的问题 终端 lsof -i:5000 kill <端口号> 强制删除 kill -s 9 <端口号> 给网页标题添加icon {% block ...

  9. 小a与星际探索---DP

    题目描述 小a正在玩一款星际探索游戏,小a需要驾驶着飞船从11号星球出发前往nn号星球.其中每个星球有一个能量指数pp.星球ii能到达星球jj当且仅当pi>pjpi>pj.同时小a的飞船还 ...

  10. 2.3 if switch for等流程控制

    if条件中可以写多个语句,语句的作用域仅限于if,不可在if之外的地方使用 package main import ( "fmt" "io/ioutil" ) ...