文档章节

【Java并发编程实战】– 在同步代码中使用条件

pan_1308
 pan_1308
发布于 2017/09/07 17:21
字数 622
阅读 9
收藏 0

一、概述

在并发编程中的一个经典问题是生产者与消费者问题:我们有一个数据缓冲区,一个或多个数据的生产者在缓冲区存储数据,而一个或多个数据的消费者,把数据从缓冲区取出。

由于缓冲区是一个共享的数据结构,我们必须采用同步机制,比如 synchronized 关键字来控制对它的访问。但是我们有更多的限制因素,如果缓冲区是满的,生产者不能存储数据,如果缓冲区是空的,消费者不能取出数据。

对于这些类型的情况,Java在Object对象中提供wait(),notify(),和notifyAll() 方法的实现。

 wait() 方法:

      1、只能在同步代码块中调用

      2、当一个线程调用 wait() 方法,jvm将这个线程置入休眠,并且释放控制这个同步代码快的对象,同时允许其他线程执行这个对象控制的其他同步代码块

      3、为了唤醒这个线程,必须在这个对象控制的某个同步代码快调用 notify() 方法或者 notifyAll() 方法

二、实现

import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 中间缓存
 */
public class EventStorage {

	private int maxSize;
	private LinkedBlockingQueue<Date> storage;
	
	public EventStorage(int maxSize){
		this.maxSize = maxSize;
		storage = new LinkedBlockingQueue<Date>();
	}
	
	// 存放操作
	public synchronized void set(){
		// 在while循环中,你必须保持检查条件和调用wait()方法。你不能继续执行,直到这个条件为true。
		while(storage.size() == maxSize){ //循环判断 为 真,才进行 线程 挂起操作.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.offer(new Date());
		System.out.println("存操作- storage size:" + storage.size());
		notifyAll(); // 唤醒 所有 因为 wait() 操作而休眠的 线程.
	}
	
	// 取出操作
	public synchronized void get(){
		while(storage.size() == 0){ //循环判断 为 真,才进行 线程 挂起操作.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.poll();
		System.out.println("取出操作- storage size:" + storage.size());
		notifyAll(); // 唤醒 所有 因为 wait() 操作而休眠的 线程.
	}
}
import java.util.concurrent.TimeUnit;

/**
 *  生产者
 */
public class EventProducer implements Runnable{

	private EventStorage eventStorage;
	
	public EventProducer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}
	
	@Override
	public void run() {
	   while(true){
		   eventStorage.set();
		   try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	   }
	}
}
/**
 * 消费者
 */
public class EventCustomer implements Runnable{
    
    private EventStorage eventStorage;
	
	public EventCustomer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}

	public void run() {
		while(true){
			eventStorage.get();
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class EventTest {

	public static void main(String[] args) {
		EventStorage eventStorage = new EventStorage(3);
		
		EventProducer producer = new EventProducer(eventStorage);
		EventCustomer customer = new EventCustomer(eventStorage);
		
		Thread threadProducer = new Thread(producer);
		Thread threadCostomer = new Thread(customer);
		
		threadProducer.start();
		threadCostomer.start();
	}
}

 

© 著作权归作者所有

共有 人打赏支持
pan_1308
粉丝 4
博文 95
码字总数 58819
作品 0
黄冈
Java面试:投行的15个多线程和并发面试题

本文由ImportNew -一杯哈希不加盐 翻译自dzone。欢迎加入翻译小组。转载请见文末要求。 多线程和并发问题已成为各种 Java 面试中必不可少的一部分。如果你准备参加投行的 Java 开发岗位面试,...

ImportNew
08/23
0
0
Java 使用 happen-before 规则实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的...

stateIs0
01/20
0
0
【死磕Java并发】—– 死磕 Java 并发精品合集

【死磕 Java 并发】系列是 LZ 在 2017 年写的第一个死磕系列,一直没有做一个合集,这篇博客则是将整个系列做一个概览。 先来一个总览图: 【高清图,请关注“Java技术驿站”公众号,回复:脑...

chenssy
07/22
0
0
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
04/16
0
0
计算机科学中抽象的好处与问题—伪共享实例分析

David John Wheeler有一句名言“计算机科学中的任何问题都可以通过加上一层间接层来解决”,一层不够就再加一层。后半句是我加的 (* ̄︶ ̄) ,虽然有点玩笑的意思,但是也的确能说明一些问题...

MageekChiu
01/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

在Debian 9系统上安装Mysql数据库的方法教程

前言 看到题目大家应都会想,在 Debian 9 上安装 Mysql?那不是很简单的事儿吗?直接 sudo apt install mysql-server 不就行了吗? 没想到遇到了几个之前没遇到的问题,耽误了不少时间。 原来...

临江仙卜算子
56分钟前
4
1
从web实时通信讲H5 WebSocket

通常我们打开一个浏览器访问网页时,都会向页面所在的服务器发送一个HTTP请求,然后web服务器确认请求并向浏览器做出响应。简单的说,就是一个请求对应的一个响应。然而这种方法对许多的应用...

Code辉
今天
4
0
Sharding-Sphere自动化执行引擎

Q: 什么叫"自动化执行引擎"? A: 一条SQL的生命周期是:从客户端发起、经过Sharding-Sphere处理、再到底层数据库执行消化。而在Sharding-Sphere里过程则是:SQL解析-->SQL优化-->SQL路由-->...

xiaomin0322
今天
2
0
单模块中ReentrantLock的使用

背景 在单模块应用中,对同一个请求,需要进行同步。注意ReentrantLock的使用场景: 同一个线程中 同一个请求 RestController @RestControllerpublic class Controller {private final Re...

亚林瓜子
今天
2
0
Linux 4.1内核热补丁成功实践

好久不见的干货重现江湖!今日的内容是基于UCloud运维同学反馈的个别宿主机上存在进程CPU峰值使用率异常现象问题进行的相关阐述。本文详细介绍了该问题的完整分析思路和用热补丁的方式成功解...

UCloudTech
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部