zoukankan      html  css  js  c++  java
  • ReentrantLock

    1.ReentrantLock概述

    在java多线程中,可以使用synchronized关键字来实现线程之间同步互斥,但在JDK1.5中增加了ReentrantLock也能达到同样的效果,并且在扩展功能上也更加强大,而且使用上更加灵活。

    使用ReentrantLock实现生产者消费者:

    package chapter4.reentrant;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class MyStack {
    	
    	private List<String> list = new ArrayList<>();
    	ReentrantLock lock = new ReentrantLock();
    	Condition conditionp = lock.newCondition();
    	Condition conditionc = lock.newCondition();
    	
    	public void push() {
    		try {
    			lock.lock();
    			while(list.size() == 1) {
    				System.out.println("push 操作中的:"+Thread.currentThread().getName()+" 线程呈等待状态");
    				conditionp.await();
    			}
    			list.add("anything="+Math.random());
    			conditionc.signalAll();
    			System.out.println("push="+list.size());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    	
    	public void pop() {
    		try {
    			lock.lock();
    			while(list.size() == 0) {
    				System.out.println("pop 操作中的:"+Thread.currentThread().getName()+" 线程呈等待状态");
    				conditionc.await();
    			}
    			String str = list.get(0);
    			System.out.println("pop "+str);
    			list.remove(0);
    			conditionp.signalAll();
    			System.out.println("pop="+list.size());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    	
    }
    
    package chapter4.reentrant;
    
    public class P {
    	private MyStack myStack;
    	public P(MyStack myStack) {
    		this.myStack = myStack;
    	}
    	
    	public void pushService() {
    		myStack.push();;
    	}
    
    }
    
    
    package chapter4.reentrant;
    
    public class C {
    	private MyStack myStack;
    	public C(MyStack myStack) {
    		this.myStack = myStack;
    	}
    	
    	public void popService() {
    		myStack.pop();;
    	}
    
    }
    
    
    package chapter4.reentrant;
    
    public class ThreadP extends Thread{
    	
    	private P p;
    	public ThreadP(P p) {
    		this.p = p;
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		p.pushService();
    	}
    
    }
    
    
    package chapter4.reentrant;
    
    public class ThreadC extends Thread{
    	
    	private C c;
    	public ThreadC(C c) {
    		this.c = c;
    	}
    	
    	@Override
    	public void run() {
    		super.run();
    		c.popService();
    	}
    
    }
    
    
    package chapter4.reentrant;
    
    public class Run {
    	
    	public static void main(String[] args) {
    		try {
    			int cnt=3;
    			MyStack myStack = new MyStack();
    			P[] pArr = new P[cnt];
    			C[] cArr = new C[cnt];
    			for(int i=0;i<cnt;i++) {
    				pArr[i] =new P(myStack); 
    				cArr[i] = new C(myStack);;
    			}
    			ThreadP[] threadPs = new ThreadP[cnt];
    			ThreadC[] threadCs = new ThreadC[cnt];
    			for(int i=0;i<cnt;i++) {
    				threadPs[i] = new ThreadP(pArr[i]);
    				threadCs[i] = new ThreadC(cArr[i]);
    			}
    			for(int i=0;i<cnt;i++) {
    				threadCs[i].start();
    			}
    			Thread.sleep(1000);
    			for(int i=0;i<cnt;i++) {
    				threadPs[i].start();
    			}
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		
    	}
    
    }
    

     运行结果:

    pop 操作中的:Thread-1 线程呈等待状态
    pop 操作中的:Thread-3 线程呈等待状态
    pop 操作中的:Thread-5 线程呈等待状态
    push=1
    push 操作中的:Thread-2 线程呈等待状态
    push 操作中的:Thread-4 线程呈等待状态
    pop anything=0.04358985658650283
    pop=0
    pop 操作中的:Thread-3 线程呈等待状态
    pop 操作中的:Thread-5 线程呈等待状态
    push=1
    push 操作中的:Thread-4 线程呈等待状态
    pop anything=0.8139775455313625
    pop=0
    pop 操作中的:Thread-5 线程呈等待状态
    push=1
    pop anything=0.8443402579212704
    pop=0

    2.ReentrantLock方法介绍

    •  int getQueueLength():返回正等待获取此锁定的线程估计数。
    package chapter4.reentrantmethod;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Service {
    	
    	public ReentrantLock lock = new ReentrantLock();
    	public void method() {
    		try {
    			lock.lock();
    			System.out.println("ThreadName:"+Thread.currentThread().getName()+"进入方法!");
    			Thread.sleep(Integer.MAX_VALUE);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    
    }
    
    package chapter4.reentrantmethod;
    
    public class Run {
    	
    	public static void main(String[] args) {
    		try {
    			final Service service = new Service();
    			Runnable runnable = new Runnable() {
    				public void run() {
    					service.method();
    				}
    			};
    			Thread[] threads = new Thread[10];
    			for(int i=0;i<10;i++) {
    				threads[i] = new Thread(runnable);
    			}
    			for(int i=0;i<10;i++) {
    				threads[i].start();
    			}
    			Thread.sleep(2000);
    			System.out.println(service.lock.getQueueLength()+"个线程在等待获取锁");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	
    	}
    
    }
    

     运行结果:

    ThreadName:Thread-0进入方法!
    9个线程在等待获取锁

    • int getHoldCount():查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
    package chapter4.reentrantmethod;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Service {
    	
    	public ReentrantLock lock = new ReentrantLock();
    	public void method1() {
    		try {
    			lock.lock();
    			System.out.println("method1 getHoldCount:"+lock.getHoldCount());
    			method2();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    	
    	public void method2() {
    		try {
    			lock.lock();
    			System.out.println("method2 getHoldCount:"+lock.getHoldCount());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    
    }
    
    package chapter4.reentrantmethod;
    
    public class Run {
    	
    	public static void main(String[] args) {
    		Service service = new Service();
    		service.method1();
    	}
    
    }
    

     运行结果:

    method1 getHoldCount:1
    method2 getHoldCount:2

    • boolean hasWaiters(Condition condition):查询是否有线程正在等待与此锁定有关的Condition条件。
    • int getWaitQueueLength(Condition condition):返回等待与此锁定条件相关的给定条件Condition的线程估计数。
    package chapter4.reentrantmethod;
    
    import java.util.concurrent.locks.Condition;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Service {
    	
    	private ReentrantLock lock = new ReentrantLock();
    	private Condition condition = lock.newCondition();
    	public void waitMethod() {
    		try {
    			lock.lock();
    			condition.await();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    	
    	public void notifyMethod() {
    		try {
    			lock.lock();
                  System.out.println("是否有线程正在等待condition:"+lock.hasWaiters(condition)); System.out.println(lock.getWaitQueueLength(condition)+"个线程正在等待condition"); condition.signalAll(); } catch (Exception e) { e.printStackTrace(); }finally { lock.unlock(); } } } package chapter4.reentrantmethod; public class Run { public static void main(String[] args) { try { final Service service = new Service(); Runnable runnable = new Runnable() { public void run() { service.waitMethod(); } }; Thread[] threads = new Thread[10]; for(int i=0;i<10;i++) { threads[i] = new Thread(runnable); } for(int i=0;i<10;i++) { threads[i].start(); } Thread.sleep(2000); service.notifyMethod(); } catch (Exception e) { e.printStackTrace(); } } }

     运行结果:

    是否有线程正在等待condition:true
    10个线程正在等待condition

    •  boolean hasQueuedThread(Thread thread):查询指定的线程是否正在等待获取此锁定。
    • boolean hasQueuedThreads():查询是否有线程正在等待获取此锁定。
    package chapter4.reentrantmethod;
    
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Service2 {
    	
    	public ReentrantLock lock = new ReentrantLock();
    	public void waitMethod() {
    		try {
    			lock.lock();
    			Thread.sleep(Integer.MAX_VALUE);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}finally {
    			lock.unlock();
    		}
    	}
    
    }
    
    package chapter4.reentrantmethod;
    
    public class Run2 {
    	
    	public static void main(String[] args) {
    		try {
    			final Service2 service = new Service2();
    			Runnable runnable = new Runnable() {
    				public void run() {
    					service.waitMethod();
    				}
    			};
    			Thread threada = new Thread(runnable);
    			threada.start();
    			Thread.sleep(500);
    			
    			Thread threadb = new Thread(runnable);
    			threadb.start();
    			Thread.sleep(500);
    			System.out.println(service.lock.hasQueuedThread(threada));
    			System.out.println(service.lock.hasQueuedThread(threadb));
    			System.out.println(service.lock.hasQueuedThreads());
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	
    	}
    
    }
    

     执行结果:

    false
    true
    true

    • boolean isFair():判断是不是公平锁,ReentrantLock类默认使用的是非公平锁。
    • boolean isHeldByCurrentThread():查询当前线程是否保持此锁定。
    • boolean isLocked():此锁定是否由任意线程保持。
    • void lockInterruptibly():如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
    • boolean tryLock():仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。
    • boolean tryLock(long timeout, TimeUnit unit):如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定。
    • void awaitUninterruptibly():线程被中断,不会抛出异常。
    • boolean awaitUntil(Date deadline):wait到某一个时间点,可以被提前唤醒。

    3.ReentrantReadWriteLock

    • readLock().lock();//获取读锁
    • readLock().unlock();//释放读锁
    • writeLock().lock();//获取写锁
    • writeLock().unlock();//释放写锁

    读读共享,写写互斥,读写互斥,写读互斥。

  • 相关阅读:
    ES6 promise的用法
    elementUI el-dialog 解决embed标签无法实时更新预览PDF文件
    elementUI upload 上传 传参
    elementUI form表单验证
    Ajax 原理过程 同步与异步区别 优缺点
    《深入理解mybatis原理(十二)》 mybatis深入理解之#与$区别
    截取字符串,含有汉字和字母,不能截半个汉字
    输出一个纯英文字符串中出现次数最左的单词和次数,如果有几个次数最多的单词,全部输出
    极简主义生活方式
    MySQL中创建表指定存储引擎
  • 原文地址:https://www.cnblogs.com/hunter-56213/p/11090316.html
Copyright © 2011-2022 走看看