lock+Condition
关键字 synchronized+wait/notify/notifyAll可以实现等待/通知模式,类ReentrantLock可以实现同样的功能,但需要借助Condition对象。Condition类是JDK5中出现的技术,使用它有更好的灵活性,比如可以实现多路通知功能,选择性的进行线程通知,在调度线程上更加灵活。
使用wait+notify/notifyAll方法进行通知时,被通知的线程却是由JVM随机选择的。但使用reentrantLock结合Condition类是可以实现选择性通知。
Object类中的wait()方法,相当于Condition类中的await()方法;Object类中的notify()方法,相当于Condition类中的signal()方法。Object类中的notifyAll方法,相当于Condition类中的signalAll()方法。
打印 12A34B.......5152Z
1 import java.util.concurrent.locks.Condition; 2 import java.util.concurrent.locks.Lock; 3 import java.util.concurrent.locks.ReentrantLock; 4 5 public class Print12A_RC { 6 7 private Lock lock =new ReentrantLock(); 8 private Condition con=lock.newCondition(); 9 private boolean isInt=true; 10 private int i=1; 11 private char ch ='A'; 12 public void printInt() 13 { 14 try { 15 lock.lock(); 16 while(!isInt) 17 { 18 con.await(); 19 } 20 System.out.print((i++)+""+(i++)); 21 isInt=false; 22 con.signal(); 23 } catch (Exception e) { 24 } 25 finally 26 { 27 lock.unlock(); 28 } 29 } 30 31 public void printChar() 32 { 33 try { 34 lock.lock(); 35 while(isInt) 36 { 37 con.await(); 38 } 39 System.out.print((char)ch); 40 ch++; 41 isInt=true; 42 con.signal(); 43 44 45 } catch (Exception e) { 46 } 47 finally { 48 lock.unlock(); 49 } 50 } 51 52 public static void main(String[] args) { 53 Print12A_RC rc=new Print12A_RC(); 54 Thread aThread=new Thread(new Runnable() { 55 56 @Override 57 public void run() { 58 for(int i=0;i<26;i++) 59 { 60 rc.printInt(); 61 } 62 } 63 }); 64 Thread bThread =new Thread(new Runnable() { 65 66 @Override 67 public void run() { 68 for(int i=0;i<26;i++) 69 { 70 rc.printChar(); 71 } 72 } 73 }); 74 aThread.start(); 75 bThread.start(); 76 } 77 }
顺序打印,如123123123....
1 package multiMethod.reentrantLockCondition; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.ReentrantLock; 5 6 public class PrintByOrder { 7 ReentrantLock lock =new ReentrantLock(); 8 Condition condition=lock.newCondition(); 9 int printnext=1; 10 11 public void print1() 12 { 13 lock.lock(); 14 try{ 15 while(printnext!=1) 16 { 17 condition.await(); 18 } 19 Thread.sleep(500);//不加此行会不打印,不知什么原因。 20 System.out.print(1); 21 printnext=2; 22 condition.signalAll(); 23 } 24 catch (Exception e) { 25 // TODO: handle exception 26 } 27 finally{ 28 lock.unlock(); 29 } 30 } 31 32 public void print2() 33 { 34 lock.lock(); 35 try{ 36 while(printnext!=2) 37 { 38 condition.await(); 39 } 40 System.out.print(2); 41 printnext=3; 42 condition.signalAll(); 43 } 44 catch (Exception e) { 45 } 46 finally{ 47 lock.unlock(); 48 } 49 } 50 51 public void print3() 52 { 53 lock.lock(); 54 try{ 55 while(printnext!=3) 56 { 57 condition.await(); 58 } 59 System.out.print(3); 60 printnext=1; 61 condition.signalAll(); 62 } 63 catch (Exception e) { 64 // TODO: handle exception 65 } 66 finally{ 67 lock.unlock(); 68 } 69 } 70 71 public static void main(String[] args) { 72 PrintByOrder order=new PrintByOrder(); 73 Runnable runnable1=new Runnable() { 74 75 @Override 76 public void run() { 77 while(true){ 78 order.print1(); 79 } 80 } 81 }; 82 83 Runnable runnable2=new Runnable() { 84 85 @Override 86 public void run() { 87 while(true){ 88 order.print2(); 89 } 90 } 91 }; 92 93 Runnable runnable3=new Runnable() { 94 95 @Override 96 public void run() { 97 while(true){ 98 order.print3(); 99 } 100 } 101 }; 102 103 new Thread(runnable1).start(); 104 new Thread(runnable2).start(); 105 new Thread(runnable3).start(); 106 } 107 }
读写锁,比上面的lock+condition提高效率。
ReentrantReadWriteLock会使用两把锁来解决问题,一个读锁,一个写锁
线程进入读锁的前提条件:
没有其他线程的写锁,
没有写请求或者有写请求,但调用线程和持有锁的线程是同一个
线程进入写锁的前提条件:
没有其他线程的读锁
没有其他线程的写锁
简单来说,就是读读共享,写写互斥,读写互斥。
另外,ReentrantReadWriteLock.readLock 无需newCondition,而ReentrantReadWriteLock.writeLock可以newCondition,用于多个读线程之间的通信。
1 import java.util.concurrent.locks.ReentrantReadWriteLock; 2 3 public class ReadWriteLock { 4 private ReentrantReadWriteLock rw= new ReentrantReadWriteLock(); 5 6 public void readLock(){ 7 8 9 try { 10 rw.readLock().lock(); 11 System.out.println("read before sleep:"+Thread.currentThread().getName()+":"+System.currentTimeMillis()); 12 Thread.sleep(2000); 13 System.out.println("read after sleep:"+Thread.currentThread().getName()+":"+System.currentTimeMillis()); 14 } catch (Exception e) { 15 // TODO: handle exception 16 }finally{ 17 rw.readLock().unlock(); 18 } 19 } 20 21 public void writeLock(){ 22 23 24 try { 25 rw.writeLock().lock(); 26 System.out.println("write before sleep:"+Thread.currentThread().getName()+":"+System.currentTimeMillis()); 27 Thread.sleep(2000); 28 System.out.println("write after sleep:"+Thread.currentThread().getName()+":"+System.currentTimeMillis()); 29 } catch (Exception e) { 30 // TODO: handle exception 31 }finally{ 32 rw.writeLock().unlock(); 33 } 34 } 35 36 public static void main(String[] args) { 37 ReadWriteLock rwl=new ReadWriteLock(); 38 Runnable runnable=new Runnable() { 39 40 @Override 41 public void run() { 42 rwl.writeLock(); 43 rwl.readLock(); 44 45 } 46 }; 47 Thread[] threads=new Thread[10]; 48 for(int i=0;i<5;i++) 49 { 50 threads[i]=new Thread(runnable); 51 } 52 for(int i=0;i<5;i++) 53 { 54 threads[i].start(); 55 } 56 } 57 58 }