Java多线程学习(九)
2016-03-09 19:01
543 查看
在JDK1.5中新增加了ReentrantLock类页能够实现同步的效果,而且在扩张功能上也更加强大,使用上也更加方便。
ReentrantLock
首先先看一下ReentrantLock的方法:
然后来看一个ReentrantLock的使用实例。
Condition
首先先看一下Condition类的方法:
Condition对象相当于“对象监视器”实例,线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。而synchronized就相当于整个Lock对象中就只有一个单一的Condition,所有线程都注册到一个Condition中,线程开始notifyAll时,需要通知所有的WAITING线程。
用Condition实现等待/通知模式
Condition中的await()方法相当于wait()方法,signal()/signalAll()方法相当于notify()/notifyAll()方法。
使用多个Condition实现通知部分线程
既要先对线程组进行分类,然后在唤醒指定组中的线程
公平锁与非公平锁
公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即按照先进先出的顺序。打印结果基本有序。
非公平锁就是一种获取锁的抢占机制,是随机获得锁的,某些线程可能一直都拿不到锁。打印结果基本乱序。默认的
Lock lock = new ReentrantLock(true); //公平锁
Lock lock = new ReentrantLock(false); //非公平锁
使用ReentrantReadWriteLock类
ReentrantLock类具有完全互斥排他的效果,即同一个时间内只有一个线程在执行lock方法后面的任务。这样的效率极低。所以JDK中提供了一种ReentrantReadWriteLock类,在某些不需要操作实例变量的方法中,可以提高代码执行速度。
读写锁有两个锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,称为排它锁。多个读锁之间不互斥,读锁和写锁互斥,写锁和写锁互斥。在没有线程进行写入操作时,进行读操作的多个线程都可以获取锁,而进行写操作的线程只有在获取写锁之后才能进行写入操作。即多个线程可以同时进行读取操作,但是同一个时刻只允许一个线程进行写操作。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.writeLock().lock();
ReentrantLock
首先先看一下ReentrantLock的方法:
然后来看一个ReentrantLock的使用实例。
public class Service extends Thread { private Lock lock = new ReentrantLock(); public void run(){ lock.lock(); for(int i = 0; i < 5; i++){ System.out.println(Thread,currentThread().getName()); } lock.unLock(); } public static void main(String [] args){ Service s1 = new Service(); Service s2 = new Service(); Service s3 = new Service(); s1.start(); s2.start(); s3.start(); } 运行结果:每个线程是同步的,但哪个线程先执行是不一定的。调用ReentrantLock对象的lock()方法获取锁,调用unlock()方法释放锁。unLock()方法也可放到finally代码块中。
Condition
首先先看一下Condition类的方法:
Condition对象相当于“对象监视器”实例,线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。而synchronized就相当于整个Lock对象中就只有一个单一的Condition,所有线程都注册到一个Condition中,线程开始notifyAll时,需要通知所有的WAITING线程。
public class MyThread extends Thread { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void run(){ lock.lock(); condition.await(); lock.unLock(); } public static void main(String [] args){ MyThread t = new MyThread(); t.start(); } }在调用Condition的await方法之前,必须要先获得锁,即必须先调用Lock的lock方法,否则会抛出异常。
用Condition实现等待/通知模式
Condition中的await()方法相当于wait()方法,signal()/signalAll()方法相当于notify()/notifyAll()方法。
使用多个Condition实现通知部分线程
既要先对线程组进行分类,然后在唤醒指定组中的线程
public class MyService { private Lock lock = new ReentrantLock(); private Condition conditionA = lock.newCondition(); private Condition conditionB = lock.newCondition(); public void awaitA(){ lock.lock(); conditionA.await(); lock.unLock(); } public void awaitB(){ lock.lock(); conditionB.await(); lock.unLock(); } public void signalA(){ lock.lock(); conditionA.signalAll(); lock.unLock(); } public void signalB(){ lock.lock(); conditionB.signalAll(); lock.unLock(); } }调用conditionB的signalAll方法只有ConditionB的waiting线程被唤醒,而不会唤醒conditionAl的waiting线程。
公平锁与非公平锁
公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即按照先进先出的顺序。打印结果基本有序。
非公平锁就是一种获取锁的抢占机制,是随机获得锁的,某些线程可能一直都拿不到锁。打印结果基本乱序。默认的
Lock lock = new ReentrantLock(true); //公平锁
Lock lock = new ReentrantLock(false); //非公平锁
使用ReentrantReadWriteLock类
ReentrantLock类具有完全互斥排他的效果,即同一个时间内只有一个线程在执行lock方法后面的任务。这样的效率极低。所以JDK中提供了一种ReentrantReadWriteLock类,在某些不需要操作实例变量的方法中,可以提高代码执行速度。
读写锁有两个锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,称为排它锁。多个读锁之间不互斥,读锁和写锁互斥,写锁和写锁互斥。在没有线程进行写入操作时,进行读操作的多个线程都可以获取锁,而进行写操作的线程只有在获取写锁之后才能进行写入操作。即多个线程可以同时进行读取操作,但是同一个时刻只允许一个线程进行写操作。
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.writeLock().lock();
相关文章推荐
- Spring源码解析 - BeanFactory
- Struts2学习笔记(一):简介和环境搭建
- java类加载过程
- java 遍历文件夹中的所有文件
- Java - HashSet
- java cookie全解析
- Java与设计模式-适配器模式
- Java中的代码块
- Java常见乱码问题总结
- java之常用正则表达式
- Java集合:Hashtable使用详解及源码分析
- javaWeb-Servlet之Filter(过滤器二)
- Java 多线程(四)——线程同步(synchronized、ReentrantLock)
- 深入分析 Java 中的中文编码问题
- myeclipse 中如何更换 SVN账户
- Shiro学习--与SpringMVC整合(数据库,Shiro注解和Shiro标签)
- Eclipse 安装反编译插件jadClipse(转)
- Struts2的简单认识
- java学习之自定义异常
- java中类序列化与反序列化的实现