JDK1.5新特性——Lock、Condition接
2015-09-21 22:23
417 查看
我们知道,多线程中往往会对同一资源数据进行操作,这就意味着需要同步处理。
同步处理的过程:某线程拿到锁,持有锁,进行数据操作,释放锁。
同步处理的原则:保证对数据操作的完整性。
以往我们用synchronized修饰函数或定义synchronized语句块来实现同步处理的过程,我们只需要定义怎么处理数据就行了,而不考虑锁什么时候锁上、什么时候打开。同步函数的锁往往是本类对象的this引用或本类的字节码对象。
而在JDK1.5中,提供了一种锁处理机制,即Lock、Condition接口。这里需要手动上锁、手动开锁。
而且新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。
这两个接口都是在java.util.concurrent.locks下的,所有使用时需要导包。
1
1.1
1.1.1 void
获取锁。可以让别的线程无法执行已上锁的代码。
1.1.2 void
释放锁。允许别的线程访问此代码。
Locklock = newReentrantLock();//父类引用指向子类对象。
Condition condition =lock.newCondition();
2.1.1 void
使当前线程进入阻塞(等待)状态。
2.1.2 void
唤醒一个等待线程。
2.1.3 void
唤醒所有等待线程。
新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。
看4.2改写多生产多消费的程序,也没有体现出比synchronized更加灵活的地方来,依旧是唤醒所有的程序啊?
一个lock实例产生两个Condition对象,分别对不同的线程加以标记,从而进行不同的操作。
同步处理的过程:某线程拿到锁,持有锁,进行数据操作,释放锁。
同步处理的原则:保证对数据操作的完整性。
以往我们用synchronized修饰函数或定义synchronized语句块来实现同步处理的过程,我们只需要定义怎么处理数据就行了,而不考虑锁什么时候锁上、什么时候打开。同步函数的锁往往是本类对象的this引用或本类的字节码对象。
而在JDK1.5中,提供了一种锁处理机制,即Lock、Condition接口。这里需要手动上锁、手动开锁。
而且新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。
这两个接口都是在java.util.concurrent.locks下的,所有使用时需要导包。
1
接口Lock
1.1
方法
1.1.1 void
lock()
获取锁。可以让别的线程无法执行已上锁的代码。1.1.2 void
unlock()
释放锁。允许别的线程访问此代码。1.1.3 ConditionnewCondition()
返回绑定到此Lock实例的新Condition实例。1.2 实现Lock接口的类
1.2.1 ReentrantLock
一个可重入的互斥锁Lock,它具有与使用synchronized方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。Locklock = newReentrantLock();//父类引用指向子类对象。
Condition condition =lock.newCondition();
2 接口Condition
2.1 方法
2.1.1 void
await() throws InterruptedException
使当前线程进入阻塞(等待)状态。2.1.2 void
signal()
唤醒一个等待线程。2.1.3 void
signalAll()
唤醒所有等待线程。3 使用方法
class Resource { //公共资源属性 boolean flag = true; //标记值 final Lock lock = new ReentrantLock(); //生产一个锁(父类引用指向子类对象) final Condition condition = lock.newCondition();//用生成的锁Condition实例 //同一个锁可以有n个不同的Condition实例,分别对不同的线程起作用哦 void set(公共资源) { lock.lock();//加锁 try { if(!flag) //多线程 用while判断 condition.await(); //满足条件,等待(等待前finally释放锁) //对公共资源的操作(写操作,生产) flag = false; condition.signal();//唤醒其他线程 //多线程 用signalAll()唤醒全部线程 } catch(InterruptedException e) {//异常处理:1、try-catch处理 2、throws处理(如下) } finally { lock.unlock();//释放锁 } } void get() throws InterruptedException //异常处理:抛给调用者处理 { lock.lock(); try { if(flag) condition.await(); //对公共资源的操作(读操作,消费) flag = true; condition.signal(); } finally { lock.unlock(); } } }
4 改写程序
4.1 改写单生产单消费的程序
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Goods { String name; int id = 0; boolean flag = true; final Lock lock = new ReentrantLock(); final Condition condition = lock.newCondition(); void set(String name) throws InterruptedException { lock.lock(); try { if(!flag) condition.await(); this.name = name; id++; System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id); flag = false; condition.signal(); } finally { lock.unlock(); } } void get() { lock.lock(); try { if(flag) condition.await(); System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id); flag = true; condition.signal(); } catch(InterruptedException e) { } finally { lock.unlock(); } } } class SetGoods implements Runnable { private Goods goods; public SetGoods(Goods goods) { this.goods = goods; } public void run() { int n = 500; while(n-- > 0) { try { goods.set("汉堡"); } catch(InterruptedException e) { } } } } class GetGoods implements Runnable { private Goods goods; public GetGoods(Goods goods) { this.goods = goods; } public void run() { int n = 500; while(n-- > 0) goods.get(); } } public class Main { public static void main(String[] args) { Goods goods = new Goods(); new Thread(new SetGoods(goods), "A生产").start(); new Thread(new GetGoods(goods), "C消费").start(); } }
4.2 改写多生产多消费的程序
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; class Goods { String name; int id = 0; boolean flag = true; final Lock lock = new ReentrantLock(); final Condition condition = lock.newCondition(); void set(String name) throws InterruptedException { lock.lock(); try { while(!flag) condition.await(); this.name = name; id++; System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id); flag = false; condition.signalAll(); } finally { lock.unlock(); } } void get() { lock.lock(); try { while(flag) condition.await(); System.out.println(Thread.currentThread().getName()+"--商品--"+name+"--"+id); flag = true; condition.signalAll(); } catch(InterruptedException e) { } finally { lock.unlock(); } } } class SetGoods implements Runnable { private Goods goods; public SetGoods(Goods goods) { this.goods = goods; } public void run() { int n = 500; while(n-- > 0) { try { goods.set("汉堡"); } catch(InterruptedException e) {} } } } class GetGoods implements Runnable { private Goods goods; public GetGoods(Goods goods) { this.goods = goods; } public void run() { int n = 500; while(n-- > 0) goods.get(); } } public class Main { public static void main(String[] args) { Goods goods = new Goods(); new Thread(new SetGoods(goods), "A生产").start(); new Thread(new SetGoods(goods), "B生产").start(); new Thread(new GetGoods(goods), "C消费").start(); new Thread(new GetGoods(goods), "D消费").start(); } }
新特性更加的灵活。举个例子,在多生产多消费的线程中,我们用while循环来判断,用notifyAll()来唤醒所有的线程,那么不能只单单唤醒对方阵营中某一线程吗?而利用Lock、Condition是能实现的。
看4.2改写多生产多消费的程序,也没有体现出比synchronized更加灵活的地方来,依旧是唤醒所有的程序啊?
5 使用方法升级版
class Resource { //公共资源属性 boolean flag = true; final Lock lock = new ReentrantLock(); final Condition conditionProduce = lock.newCondition(); //lock产生两个Condition对象 final Condition conditionConsume = lock.newCondition(); void set(公共资源) { lock.lock(); try { while(!flag) conditionProduce.await();//是当前线程等待 //数据操作 flag = false; conditionConsume.signal();//将对方阵营中的一个线程唤醒 } catch(Exception e) {} finally //必执行代码块 { lock.unlock(); } } void get() { lock.lock(); try { while(!flag) conditionConsume.await();//是当前线程等待 //数据操作 flag = false; conditionProduce.signal();//将对方阵营中的一个线程唤醒 } catch(Exception e) {} finally //必执行代码块 { lock.unlock(); } } }
一个lock实例产生两个Condition对象,分别对不同的线程加以标记,从而进行不同的操作。
6 你会再次改写多生产多消费的例子吗?
相关文章推荐
- java编程基础2
- SpringMVC与Struts2的对比
- 构造函数、、set与get方法
- Java中字符和byte数组之间的相互转换
- Android开发环境搭建——Eclipse
- maven+springMVC+mybatis 搭建资料收集
- C#/Java 调用WSDL接口及方法
- Java HashMap的死循环
- Java关键字instanceof
- 难经6:小心,SpringAOP声明式事务的一个缺陷
- 深入理解Java:内省(Introspector)
- struts2总结五: Strut2 访问Servlet API
- Java基础学习总结(二)
- 在web.xml中注册IntrospectorCleanupListener监听器以解决struts等框架可能产生的内存泄露问题
- Java反射与内省(Introspector)
- Java 开发环境搭建
- JAVA学习笔记
- java.lang.string
- Java基础学习总结(一)——Java开发学习介绍
- 理解Java对象序列化