线程间的通信_多生产者多消费者问题_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中会启动一个线程( ...
随机推荐
- bash中通过设置PS1变量改变提示符颜色
参考 <Prompt Magic> ubuntu初始时bash提示符的颜色同程序输出的颜色相同,当大量有输出时,找到输出信息开始的地方往往很费劲.如果把提示符的颜色变成更为醒目的颜色,那么 ...
- [转]Angular4 自制分页控件
本文转自:https://blog.csdn.net/Junyuan_123/article/details/79486276 过年后第一波,自制的分页控件,可能功能没有 PrimeNG 那么好,但是 ...
- 【Java并发编程】17、SynchronousQueue源码分析
SynchronousQueue是一种特殊的阻塞队列,不同于LinkedBlockingQueue.ArrayBlockingQueue和PriorityBlockingQueue,其内部没有任何容量 ...
- [转*译]Networking API Improvements in Windows 10
在当今,以云优先,移动优先技术为宗旨的时代下,大多数Apps都至少有一些与web服务或网络上其他设备的集成.这些包括应用程序,它获取天气在线内容,新闻或体育比赛的分数,媒体或下载的播客,甚至对 ...
- SVN多项目并行版本管理解决方案
1.背景 随着公司业务拓展,各业务部门频繁的需求变更,导致系统集成冲突的问题日益突出. 2.现状 基于SVN版本管理模式,多分支版本并行,分支合并主干交付.多分支开发存在依赖关系且有交付的先后顺序, ...
- docker swarm 搭建及跨主机网络互连案例分析
准备工作 安装docker,不建议直接使用Docker官方的yum install docker wget http://yum.dockerproject.org/repo/main/centos/ ...
- canvas-3linearGradient.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java 多线程简单例子
实现线程的方式是一,继承Thread类,重写父类的run()方法 二,实现接口Runnable中的run()方法. 下面是简单的例子 例子1:银行存取钱问题 package com.direct.de ...
- Csharp: read Sybase SQL anywhere5.5 using c#
private void button1_Click(object sender, EventArgs e) { try { //OdbcConnection conn = new OdbcConne ...
- input上传文件个数控制
HTML: <h3>请上传[2,5]个文件</h3> <form action="" enctype="multipart/form-dat ...