Lock+Condition 相对于 wait+notify 的一个优势案例分析

问题的描述

启动3个线程打印递增的数字, 线程1先打印1,2,3,4,5, 然后是线程2打印6,7,8,9,10, 然后是线程3打印11,12,13,14,15. 接着再由线程1打印16,17,18,19,20....以此类推, 直到打印到45.

wait+notify实现:

package com.tonyluis;
public class NumberPrintDemo {
	static int n = 1;
	static int state = 0;
	public static void main(String[] args) {
		new Thread(new MyThread(0)).start();
		new Thread(new MyThread(1)).start();
		new Thread(new MyThread(2)).start();
	}
}

class MyThread implements Runnable{
	private int state;
	MyThread(){
		this(0);
	}
	MyThread(int state){
		this.state=state;
	}
	public void run() {
		String threadName=Thread.currentThread().getName();
		for (int i = 0; i < 3; i++) {
			synchronized (MyThread.class) {
				while (state != NumberPrintDemo.state)
					try {
						MyThread.class.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				for (int j = 0; j < 5; j++)
					System.out.println(threadName+ ": " + NumberPrintDemo.n++);
				System.out.println();
				NumberPrintDemo.state++;
				NumberPrintDemo.state%=3;
				MyThread.class.notifyAll();
			}
		}
	}
}

Lock+condition实现:

package com.tonyluis;
import java.util.concurrent.locks.*;
public class NumberPrint {
	static int state = 0;
	static int n = 1;
	static Lock lock = new ReentrantLock();
	static Condition condition[]=new Condition[3];
	public static void main(String[] args) {
		for(int i=0;i<condition.length;i++)
			condition[i]=lock.newCondition();
		new Thread(new MyThread(0)).start();
		new Thread(new MyThread(1)).start();
		new Thread(new MyThread(2)).start();
	}
}
class MyThread implements Runnable{
	private int state;
	MyThread(){
		this(0);
	}
	MyThread(int state){
		this.state=state;
	}
	public void run() {
		String threadName=Thread.currentThread().getName();
		for (int i = 0; i < 5; i++) {
			try {
				NumberPrint.lock.lock();
				while (state != NumberPrint.state)
					try {
						NumberPrint.condition[state].await();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				for (int j = 0; j < 5; j++)
					System.out.println(threadName+ ": " + NumberPrint.n++);
				System.out.println();
				NumberPrint.state++;
				NumberPrint.state%=NumberPrint.condition.length;
				NumberPrint.condition[NumberPrint.state].signal();
			} finally {
				NumberPrint.lock.unlock();
			}
		}
	}
	}

使用wait+notify的实现方式,在线程0进入notifyAll()方法之后,会唤醒线程1和线程2,线程1和线程2以及线程0会展开竞争,虽然最终是由线程1获得琐,过程可能比较曲折。

使用lock+condition的实现方法,线程0只会唤醒线程1,这样只有线程1和线程0展开竞争,较为精确,尤其是并发量比较大的情况下。

时间: 2024-08-26 15:41:18

Lock+Condition 相对于 wait+notify 的一个优势案例分析的相关文章

javascript一个作用域案例分析

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script type="text/javascript"> // 词法作用域: // 在js中只有函数能够形成一个作用域, 所以, 词

线程间通信 Object/wait(),notify() 和 Lock/Condition/await(),signal()

基本前提知识: 一:Object/wait(), notify(), notifyAll() 1:wait() 方法暂停当前线程,并立即释放对象锁; 2:notify()/notifyAll() 方法唤醒其他等待该对象锁的线程,并在执行完同步代码块中的后续步骤后,释放对象锁 3:notify()和notifyAll()的区别在于: notify只会唤醒其中一个线程, notifyAll则会唤醒全部线程. 至于notify会唤醒哪个线程,是由线程调度器决定的. 例子: public class T

Lock&amp;Condition实现线程同步通信

一,Lock Lock比传统的线程模型中的synchronized方式更加面向对象,因为"锁"本身就是一个对象. 两个线程执行的代码要实现同步互斥的效果,他们必须用同一个Lock对象. 读写锁:(1)读锁:多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,我们只需要代码中用对相应的锁即可.如果只读数据,那么可以很多人(线程)同时读,但是不能同时写,此时就加读锁.如果代码需要修改数据,此时只能一个人(一个线程)写,此时不能同时读,那么就加写锁. 总之,读时,上读锁:写时,上写锁.

Lock+Condition实现机制

前言:大部分多线程同步场景,在功能和性能层面,synchronized可以满足,少部分场景Lock可以满足,dubbo的源码也符合这个比例,需要使用到Condition的场景极少,整个dubbo源码中只在启动函数中,服务关闭这一处使用到了Lock+Condition机制. 1.Lock+Condition用法 生产者,消费者模式在面试coding中出场率很高,可以用synchronized+wait+ notify来实现,也可以使用Lock+Condition实现.直接上代码 public cl

Java多线程——Lock&amp;Condition

Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. package java_thread; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { /** * @param args */ pu

Lock&Condition实现线程同步通信

import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionCommunication {     final Business business = new Business();     public static void main(Stri

(转)一个MySQL 5.7 分区表性能下降的案例分析

一个MySQL 5.7 分区表性能下降的案例分析 原文:http://www.talkwithtrend.com/Article/216803 前言 希望通过本文,使MySQL5.7.18的使用者知晓分区表使用中存在的陷阱,避免在该版本上继续踩坑.同时通过对源码的分享,升级MySQL5.7.18时分区表性能下降的根本原因,向MySQL源码爱好者展示分区表实现中锁的运用. 问题描述 MySQL 5.7版本中,性能相关的改进非常多.包括临时表相关的性能改进,连接建立速度的优化和复制分发相关的性能改进

一个拓扑,搞定BGP13条路径选择算法 - 案例分析

1.1.BGP协议最佳路径选择算法 BGP是一个路径矢量路由协议,也就是说,它的工作就是在自主系统间交换路由信息,以便发现访问互联网某处数据的最有效路径.每个 BGP路由器通过邻居声名与周边的一个或多个路由器连接.一旦建立了邻居关系,这些BGP路由器之间就会相互交换路由信息.据我最近一次统计,整个互联网上有大约12.5万个路由信息,因此要配备一个强大的路由器才能将所有BGP路由信息接收下来. 1.1.1.BGP 最佳路径选择算法概述 由于整个互联网的BGP路由表有超过30万个路由,同时一个BGP

用node.js对一个英语句子分析页面进行一个小爬虫

最近遇到一个需求,就是要从一个英语句子分析的页面中,根据你输入的英语从句,点击开始分析按钮,这个页面就会将分析的结果解析出来,如 然后我们就是需要从这个页面中把这些解析好的数据(包括句子语法结构详解,句子相关词汇解释等)取出来,这时候我就想到之前学过node.js,这时候就来弄下node.js的小小的爬虫. 首先,电脑要先安装node.js,至于怎么安装,请google,或者找相关教程来看. 然后就需要了解下node,现在我先加载http模块,然后设置url的值,url就是你要爬的那个网页的地址