本文可作为传智播客《张孝祥-Java多线程与并发库高级应用》的学习笔记。

上面我们说了Lock,那是对synchronized的一种更为面向对象的替代,在原来的synchronized内部,我们可以调用object的wait与notify方法,那么使用lock之后,如何进行线程的通信呢。

对锁不清楚的朋友可以看看

http://blog.csdn.net/dlf123321/article/details/42919085

答案是condition。

condition一方面是对lock功能的补充(也就是说,你用了lock,为了保证线程的通信,就得用condition)

另一方面,synchronized的notifyall是唤醒所有等待的线程,那么如果有些线程我不想唤醒呢。

看下面这个例子

主线程运行10次,然后子线程2运行20次,接着子线程3运行30次

上面的整体运行4次。

我们分析一下,主线程运行10次之后,下面一方面让自己阻塞,同时应该唤醒子线程2,并且不能唤醒子线程3。

如果用notifyAll就等于把线程2与线程3都唤醒了。

我们在这里说明一下

Reentrantlock相比较于synchronized还少有三个优势

1 等待可中断  具体的例子参考  http://uule.iteye.com/blog/1488356

2 实现公平锁 就是线程a在操作某个对象,线程b,c,d后面又依次来了,如果是非公平锁,那么等a结束后,bcd接手的概率是一样的,如果是公平锁那么a完了之后就是b

    synchronized是非公平的是,Reentrantlock默认情况下也是非公平的,但可以通过有带Boolean只的构造函数构建一个公平锁

3 绑定多个条件 也就是下面讲的

4  有三种使用方式

    a)  lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁

    b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;

    c)tryLock(long timeout,TimeUnit unit),   如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false; 

参考资料 http://houlinyan.iteye.com/blog/1112535

另外我得说明一点

就性能来说,在java6之后,reentrantlock与synchronized已经差不多了

而且Reentrantlock得主动释放

所有到底选择哪个实现互斥,大家还是得考虑一下

看看方法









常用的就是await与signal。

这个两个就刚好对应object的wait与notify。





我们看代码:

package cn.itcast.heima2;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreeConditionCommunication {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final Business business = new Business();
		new Thread(
				new Runnable() {

					@Override
					public void run() {

						for(int i=1;i<=4;i++){
							business.sub2(i);
						}

					}
				}
		).start();

		new Thread(
				new Runnable() {

					@Override
					public void run() {

						for(int i=1;i<=4;i++){
							business.sub3(i);
						}

					}
				}
		).start();		

		for(int i=1;i<=4;i++){
			business.main(i);
		}

	}

	static class Business {
			Lock lock = new ReentrantLock();
			Condition condition1 = lock.newCondition();
			Condition condition2 = lock.newCondition();
			Condition condition3 = lock.newCondition();
		  private int shouldSub = 1;
		  public  void sub2(int i){
			  lock.lock();
			  try{
				  while(shouldSub != 2){
					  try {
						condition2.await();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				  }
					for(int j=1;j<=20;j++){
						System.out.println("sub2 thread sequence of " + j + ",loop of " + i);
					}
				  shouldSub = 3;
				  condition3.signal();
			  }finally{
				  lock.unlock();
			  }
		  }

		  public  void sub3(int i){
			  lock.lock();
			  try{
				  while(shouldSub != 3){
					  try {
						condition3.await();
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				  }
					for(int j=1;j<=30;j++){
						System.out.println("sub3 thread sequence of " + j + ",loop of " + i);
					}
				  shouldSub = 1;
				  condition1.signal();
			  }finally{
				  lock.unlock();
			  }
		  }		  

		  public  void main(int i){
			  lock.lock();
			  try{
				 while(shouldSub != 1){
				  		try {
							condition1.await();
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				  	}
					for(int j=1;j<=10;j++){
						System.out.println("main thread sequence of " + j + ",loop of " + i);
					}
					shouldSub = 2;
					condition2.signal();
		  }finally{
			  lock.unlock();
		  }
	  }

	}
}

聊聊Condition的更多相关文章

  1. ReentrantReadWriteLock读写锁的使用1

    本文可作为传智播客<张孝祥-Java多线程与并发库高级应用>的学习笔记. 一个简单的例子 两个线程,一个不断打印a,一个不断打印b public class LockTest { publ ...

  2. 聊聊高并发(十四)理解Java中的管程,条件队列,Condition以及实现一个堵塞队列

    这篇里面有一些主要的概念,理解概念是件有意义的事情,仅仅有理解概念才干在面对详细问题的时候找到正确的解决思路.先看一下管程的概念 第一次在书上看到管程这个中文名称认为非常迷糊,管程究竟是个什么东东,于 ...

  3. 聊聊并发(七)——Java中的阻塞队列

    3. 阻塞队列的实现原理 聊聊并发(七)--Java中的阻塞队列 作者 方腾飞 发布于 2013年12月18日 | ArchSummit全球架构师峰会(北京站)2016年12月02-03日举办,了解更 ...

  4. 聊聊高并发(十八)理解AtomicXXX.lazySet方法

    看过java.util.concurrent.atomic包里面各个AtomicXXX类实现的同学应该见过lazySet方法.比方AtomicBoolean类的lazySet方法 public fin ...

  5. 聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁

    这篇讲讲ReentrantReadWriteLock可重入读写锁,它不仅是读写锁的实现,而且支持可重入性. 聊聊高并发(十五)实现一个简单的读-写锁(共享-排他锁) 这篇讲了怎样模拟一个读写锁. 可重 ...

  6. 并发王者课-铂金6:青出于蓝-Condition如何把等待与通知玩出新花样

    欢迎来到<[并发王者课](https://juejin.cn/post/6967277362455150628)>,本文是该系列文章中的**第19篇**. 在上一篇文章中,我们介绍了阻塞队 ...

  7. 聊聊Unity项目管理的那些事:Git-flow和Unity

    0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...

  8. Mono为何能跨平台?聊聊CIL(MSIL)

    前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力 ...

  9. java 线程 Lock 锁使用Condition实现线程的等待(await)与通知(signal)

    一.Condition 类 在前面我们学习与synchronized锁配合的线程等待(Object.wait)与线程通知(Object.notify),那么对于JDK1.5 的 java.util.c ...

随机推荐

  1. 【NOIP2012TG】solution

    D1T1(Vigenere) 题意:给你一个原串与一个密码串,问你按照题意规则加密后的密文. 解题思路:暴力模拟. #include <stdio.h> ],c[],u1[],u2[]; ...

  2. bzoj 1880: [Sdoi2009]Elaxia的路线

    Description 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希 ...

  3. poj 1265 Area 面积+多边形内点数

    Area Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5861   Accepted: 2612 Description ...

  4. ajax中基本参数应用

    $(function () { $("#verificationCodeBtn").click(function () { $("#verificationCodeIma ...

  5. substr函数用法详解

    substr(string, start<,length>):从string的start位置开始提取字符串 length:要提取字符串的长度,若length为以下任意条件之一时,返回sta ...

  6. python 循环和file操作实现用户密码输错三次将用户锁定

    一.需求编写登录接口1.输入用户名密码2.认证成功后显示欢迎信息3.输错三次后锁定 二.简单思路登录,三次密码输入错误锁定用户1.用户信息文件:存放用户名和密码2.黑名单文件:将输入三次错误的用户加入 ...

  7. Docker快速配置指南

    下面是一个跟 Docker 网络相关的命令列表. 其中有些命令选项只有在 Docker 服务启动的时候才能配置,而且不能马上生效. -b BRIDGE or --bridge=BRIDGE --指定容 ...

  8. HTML DOM 改变 HTML 内容

    HTML DOM 允许 JavaScript 改变 HTML 元素的内容. 改变 HTML 输出流 JavaScript 能够创建动态的 HTML 内容: 今天的日期是: Thu Feb 25 201 ...

  9. EntityFramework Core 自动绑定模型映射

    笔者最近在和同事共同开发项目时,需要从他们提供的包含数据库实体类型的类库中读取实体信息绑定到自己的项目中(但是都在同一个解决方案里),所以很直接的一种方式就是把项目中所有的实体都以 public Db ...

  10. 重温java基础

    Java标识符 Java所有的组成部分都需要名字.类名.变量名以及方法名都被称为标识符. 关于Java标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z或者a-z),美元符($).或者下划 ...