线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock
对于同步代码块,对于锁的操作是隐式的
但是在JDK1.5之前的这种方法效率有点低,判断会很多,后面升级之后有新的解决方案
jdk1.5以后将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作
Lock接口:替代了同步代码块或者同步函数,将同步的隐式锁操作变成显示锁操作,同时更为灵活,可以一个锁上加上多组监视器
lock():获取锁 unlock():释放锁,通常定义在finally代码块中
Condition接口:替代了Object中的wait notify notifyAll方法,将这些监视器方法单独封装,变成了Condition监视器对象,可以喝任意锁组合
await(); singal(); singalAll();
同步代码块到lock的变化:

import java.util.concurrent.locks.*;//lock在此包中
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
Producer pro = new Producer(r);
Consumer con = new Consumer(r); Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con); t1.start();
t2.start();
t3.start();
t4.start(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock();//创建一个锁对象 public void set(String name){
lock.lock();
try{
while(flag)
try{this.wait();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
notifyAll();
}finally{
lock.unlock();
} } public void out(){
lock.lock();
try{
while(!flag)
try{this.wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name);
flag = true;
notifyAll();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
上述实例中锁换成了lock之后就不能用this来操作wait等方法了,应该用lock锁中的Condition接口中的方法,该接口将Object监视器方法(wait,notify,notifyAll)分解成不同的对象
import java.util.concurrent.locks.*;
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
Producer pro = new Producer(r);
Consumer con = new Consumer(r); Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con); t1.start();
t2.start();
t3.start();
t4.start(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock(); //通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
Condition con = lock.newCondition(); public void set(String name){
lock.lock();
try{
while(flag)
try{con.await();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
con.signalAll(); }finally{
lock.unlock();
}
} public void out(){
lock.lock();
try{
while(!flag)
try{con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); flag = true;
con.signalAll();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
上述实例只有一组监视器,既监视着生产者,又监视着消费者,可以搞两个监视器,一组监视生产者,一组监视消费者
import java.util.concurrent.locks.*;
class LockDemo{
public static void main(String[] args) {
Resrouce r = new Resrouce();
Producer pro = new Producer(r);
Consumer con = new Consumer(r); Thread t1 = new Thread(pro);
Thread t2 = new Thread(pro);
Thread t3 = new Thread(con);
Thread t4 = new Thread(con); t1.start();
t2.start();
t3.start();
t4.start(); }
} class Resrouce{
private String name;
private int count = 1;
private boolean flag = false; Lock lock = new ReentrantLock(); /*
通过已有的锁获取该锁上的监视器对象,一个锁可以有多个监视器
Condition con = lock.newCondition();
*/ //通过已有的锁获取监视器对象(两组),一组监视生产者,一组监视消费者
Condition Producer_con = lock.newCondition();
Condition Consumer_con = lock.newCondition();
public void set(String name){
lock.lock();
try{
while(flag)
try{Producer_con.await();}catch(Exception e){}
this.name = name+count;
count++;
System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
flag = true;
//con.signalAll();//会发生死锁,所以要用到notifyAll
Consumer_con.signa();//有了两组监视器后就不用signaAll方法唤醒所有线程池中的线程了,只唤醒对方的一个线程,这样效率就高很多了
}finally{
lock.unlock();
}
} public void out(){
lock.lock();
try{
while(!flag)
try{Consumer_con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"...消费者.."+this.name); flag = true;
//con.signalAll(); Producer_con.signal();
}finally{
lock.unlock();
}
}
} class Producer implements Runnable{
private Resource r;
Producer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.set("烤鸭");
}
}
} class Consumer implements Runnable{
private Resource r;
Consumer(Resource r){
this.r = r;
}
public void run(){
while(true){
r.out();
}
}
}
wait和sleep的区别:
wait和sleep都是让线程处于冻结状态的方法
区别:
1.wait可以指定时间也可以不指定。sleep必须指定时间。
2.在同步中时,对CPU的执行权和锁的处理不同.wait:释放执行权,释放锁。sleep:释放执行权,不释放锁(不同中的代码必须拿到锁才能运行)
3.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用(使用范围)
synchronized(x){
x.notify()
//或者wait()
}
4.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
线程间的通信_多生产者多消费者问题_JDK1.5新特性_Lock的更多相关文章
- Java-JUC(九):使用Lock替换synchronized,使用Condition的await,singal,singalall替换object的wait,notify,notifyall实现线程间的通信
Condition: condition接口描述了可能会与锁有关的条件变量.这些用法上与使用object.wait访问隐式监视器类似,但提供了更强大的功能.需要特别指出的是,单个lock可能与多个Co ...
- iOS开发多线程篇—线程间的通信
iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...
- Java核心知识点学习----多线程并发之线程间的通信,notify,wait
1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...
- java多线程详解(6)-线程间的通信wait及notify方法
Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...
- iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信
一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...
- 新建线程与UI线程间的通信
现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...
- C# 线程间互相通信
C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent. 一.AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过 ...
- QThread与其他线程间相互通信
转载请注明链接与作者huihui1988 QThread的用法其实比较简单,只需要派生一个QThread的子类,实现其中的run虚函数就大功告成, 用的时候创建该类的实例,调用它的start方法即可. ...
- Handler不同线程间的通信
转http://www.iteye.com/problems/69457 Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程( ...
随机推荐
- 无法启动MYSQL服务”1067 进程意外终止”解决的方法
自己一開始依照百度经验里的方法——<MySQL下载安装.配置与使用(win7x64)>去安装和配置,可是到后面步骤总是出现1067代号的错误. 慢慢折腾去解决. 这里汇总各种导致mysql ...
- (转)MySQL触发器trigger示例详解
一.什么是触发器 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合.触发器的这种特性可以协助应用在数据库端确保数据的完整性. 举个例子,比如你现在有两个表[用户表]和[ ...
- 精读JavaScript模式(六),Memoization模式与函数柯里化的应用
假期就这么结束了!十天假就有三天在路上,真的难受!想想假期除了看了两场电影貌似也没做什么深刻印象的事情.流浪地球,特效还是很赞,不过对于感情的描写还是逃不掉拖沓和尴尬的通病,对于国产科幻还是抱有支持的 ...
- SpringBoot JPA + H2增删改查示例
下面的例子是基于SpringBoot JPA以及H2数据库来实现的,下面就开始搭建项目吧. 首先看下项目的整体结构: 具体操作步骤: 打开IDEA,创建一个新的Spring Initializr项目, ...
- SpringMVC+SpringJdbc+SQLServer+EasyUI增删改查
前言 前天用SpringJdbc连接了一把SQLServer,早上起来用SpringMVC+SpringJdbc+EasUI写了个增删改查的demo,主要是熟悉下SpringMVC相关知识点,如vie ...
- Ocelot中文文档-Getting Started
Getting Started Ocelot是只在.NET Core运行,目前基于netstandard2.0构建的.如果Ocelot适合你们的话,那么这个文档会有所帮助. .NET Core 2.0 ...
- Oracle索引失效原因及解决方法
一.Oracle索引失效的原因 1使用否定关键字 !=, <> ,not in,not exist select * fromdrama where id <> 1,Mysql ...
- 移动端FastClick和editor冲突问题。
FastClick.prototype.needsClickForParent = function (target) { let parent = target.parent ...
- vue路由传参的三种基本方式
现有如下场景,点击父组件的li元素跳转到子组件中,并携带参数,便于子组件获取数据. 父组件中: <li v-for="article in articles" @click= ...
- Python 映射
python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删除成员. ...