1.Lock的使用java
private Lock lock = new ReentrantLock(); public void test(){ lock.lock(); System.out.println("#######"); lock.unlock(); }
注意:try-catch-finally结合使用,unlock()在finally里面。ide
2.使用condition实现等待/通知spa
关键字synchronized与wait()和notify()/notifyAll()方法相结合能够实现等待/通知模式,类ReentrantLock也能够实现一样的功能,但须要借助Condition对象。能够实现多路通知功能,也就是在一个Lock对象里面能够建立多个Condition实例,线程对象能够注册在指定Condition中,从而能够有选择性进行线程通知,在调度线程上更加灵活。线程
synchronized的wait()和notify(),而Condition对象,却能够选择性通知。code
2.1 使用condition API对象
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class test5 { private Lock lock = new ReentrantLock(); public Condition condition1 = lock.newCondition(); public Condition condition2 = lock.newCondition(); public void awaitA(){ try { lock.lock(); System.out.println("A等待"); condition1.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ lock.unlock(); } } public void awaitB(){ try { lock.lock(); System.out.println("B等待"); condition2.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ lock.unlock(); } } public void signalA(){ try { lock.lock(); System.out.println("通知a"); condition1.signalAll(); } finally { lock.unlock(); } // TODO: handle finally clause } public void signalB(){ try { lock.lock(); System.out.println("通知B"); condition2.signalAll(); } finally { lock.unlock(); } // TODO: handle finally clause } public static void main(String[] args) { test5 t5 = new test5(); //建立两个线程 // Thread thread1= new Thread(t5); //Thread thread2= new Thread(t5); //只通知线程1 // t5.signalA(); } }
2.二、生产者与消费模式:交替打印get
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class test6 { private Lock lock =new ReentrantLock(); private Condition condition= lock.newCondition(); private boolean hasValue= false; public void set(){ try { lock.lock(); while(hasValue == true){ condition.await(); } System.out.println("@@@"); hasValue= true; condition.signal(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } public void get(){ try { lock.lock(); while(hasValue == false){ condition.await(); } System.out.println("###"); hasValue= false; condition.signal(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } public static void main(String[] args) { test6 test6 = new test6(); //建立两个线程 //启动 } }
注意:多消费者和多生产者,使用condition.signalAll();it
3.公平锁与非公平锁io
锁Lock分为“公平锁”和“非公平锁”,公平锁表示线程获取的顺序是按照线程加锁的顺序来分配的,即先来得的FIFO先进先出的顺序。而非公平锁就是一种获取抢占机制,是随机得到锁的,和公平锁不同就是先来得不必定先获得锁,这个方式可能形成某些线程一直拿不到锁,结果也就是不公平的了。class
import java.util.concurrent.locks.ReentrantLock; public class test7 { private ReentrantLock lock; public test7(boolean isFair){//传入true表示公平锁,反之为非公平锁 super(); lock = new ReentrantLock(); } public void add(){ try { lock.lock(); } finally { lock.unlock(); } } }
4.API讲解
4.一、方法lockInterruptibly()
该方法的做用是:若是当前线程未被中断,则获取锁定,若是已经被中断则抛出异常。
4.二、tryLock()
改方法的做用是:仅在调用时锁定未被另外一个线程保持的状况下,才获取该锁。
private Lock lock = new ReentrantLock(); public void test(){ if(lock.tryLock()){ System.out.println("#######"); } }
同时,tryLock(long timeout,TimeUnit unit)的做用是,若是锁定在给等待时间内没有被另外一个线程保持,且当前线程未被中断,则获取该锁定。
4.三、使用Condition实现顺序执行
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class test8 { volatile private static int nextPrintWho =1; private static ReentrantLock lock = new ReentrantLock(); final private static Condition conditionA = lock.newCondition(); final private static Condition conditionB = lock.newCondition(); final private static Condition conditionC = lock.newCondition(); public static void main(String[] args) { Thread threadA = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 1){ conditionA.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadA"+i); } nextPrintWho = 2; conditionB.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread threadB = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 2){ conditionB.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadB"+i); } nextPrintWho = 3; conditionC.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread threadC = new Thread(){ @Override public void run() { try { lock.lock(); while(nextPrintWho != 3){ conditionC.await(); } for(int i=1; i<4;i++){ System.out.println("ThreadC"+i); } nextPrintWho = 1; conditionA.signalAll(); } catch (Exception e) { // TODO: handle exception }finally { lock.unlock(); } } }; Thread[] aAray =new Thread[5]; Thread[] bAray =new Thread[5]; Thread[] cAray =new Thread[5]; for(int i=0;i<5;i++){ aAray[i] =new Thread(threadA); bAray[i] =new Thread(threadB); cAray[i] =new Thread(threadC); aAray[i].start(); bAray[i].start(); cAray[i].start(); } } }
总结:实现线程的顺序执行,可使用:join方法,也可使用Condition。
5.使用ReentrantReadWriteLock类
读写锁表示有两个锁,一个是读操做相关的锁,也称为共享锁;另外一个是写操做相关的的锁,也叫排它锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。在没有线程进行写入操做时,进行读取操做的多个线程均可以获取锁,而进行写入的操做的线程只有在获取写锁后才能进行操做。即多个线程能够同时进行读取操做,可是同一时刻只容许一个线程进行写入操做。
import java.util.concurrent.locks.ReentrantReadWriteLock; public class test9 { private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public void read(){ try { lock.readLock(); } catch (Exception e) { // TODO: handle exception }finally { lock.readLock().unlock(); } } public void wirte(){ try { lock.writeLock(); } catch (Exception e) { // TODO: handle exception }finally { lock.writeLock().unlock(); } } }