多线程复习笔记之三【多线程中的Lock使用】

Lock

1、getHoldCount()

查询当前线程保持此锁锁定的个数,也就是调用lock方法的次数

2、int getQueueLength

返回正等待此锁定的线程估计数,例如有5个线程,1个线程首先执行await,那么调用getQueueLength返回4

3、int getWaitQueueLength(Condition condition)

返回等待与次锁定相关的给定条件Condition的线程估计数,例如有5个线程,每个线程都执行了同一个condition对象的await方法,则调用此方法返回5.

4、boolean hasQueuedThreads

查询是否有线程正在等待获取此锁定,lock.hasQueuedThread(thread)

5、boolean hasWaiters(Condition condition)

查询是否有线程正在等待与此锁定有关的condition条件

lock.hasWaiters(condition)线程数是lock.getWaitQueueLength(condition)

6、isFair

判断是否是公平锁

7、boolean isHeldByCurrentThread

查询当前线程是否保持此锁定

8、lockInterruptibly()

如果当前线程未被中断,则获取锁定,如果已经被中断则抛出异常

9、boolean tryLock()

仅在调用时锁定未被另一个线程保持的情况下,才获取 该锁定。

10、boolean tryLock(long timeout,TimeUnit unit)

如果锁定给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获取该锁定,例如:

package com.fyw.thread.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ServiceMethod {

	public ReentrantLock lock = new ReentrantLock();
	
	public Condition condition = lock.newCondition();
	
	public void awaitMethod(){
		try{
			if(lock.tryLock(3,TimeUnit.SECONDS)){
				System.out.println(Thread.currentThread().getName()+"获得锁的时间:"+System.currentTimeMillis());
				Thread.sleep(4000);
			}
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			if(lock.isHeldByCurrentThread()){
				lock.unlock();
			}
		}
	}
	
	public void notifyMethod(){
		try{
			lock.lock();
			System.out.println("有"+lock.getWaitQueueLength(condition)+"个线程等待condition");
			condition.signal();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			lock.unlock();
		}
	}
}

public static void main(String[] args) throws InterruptedException {
		final ServiceMethod service = new ServiceMethod();
		
		Runnable runnable = new Runnable(){

			@Override
			public void run() {
				System.out.println(Thread.currentThread().getName()+"调用waitMethod时间:"+System.currentTimeMillis());
				service.awaitMethod();
			}
		};
		Thread threadA = new Thread(runnable);
		threadA.setName("A");
		threadA.start();
		Thread threadB = new Thread(runnable);
		threadB.setName("B");
		threadB.start();
		
	}

输出:

A调用waitMethod时间:1544957162945
B调用waitMethod时间:1544957162945
A获得锁的时间:1544957162946

如果将sleep(4000)改成1000,输出如下:

A调用waitMethod时间:1544957292643
B调用waitMethod时间:1544957292643
B获得锁的时间:1544957292643
A获得锁的时间:1544957293643

【使用Condition实现线程顺序交叉执行】

package com.fyw.thread.lock.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Run {

	volatile private static int nextRun = 1;
	
	private static Lock lock = new ReentrantLock();
	
	private static Condition condition1 = lock.newCondition();
	
	private static Condition condition2 = lock.newCondition();
	
	private static Condition condition3 = lock.newCondition();
	
	public static void main(String[] args) {
		Thread thread1 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					lock.lock();
					while(nextRun != 1){
						condition1.await();
					}
					for(int i=0;i<3;i++){
						System.out.println("Thread1 "+(i+1));
					}
					nextRun = 2;
					condition2.signalAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					lock.unlock();
				}
			}
			
		});
		
		Thread thread2 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					lock.lock();
					while(nextRun != 2){
						condition2.await();
					}
					for(int i=0;i<3;i++){
						System.out.println("Thread2 "+(i+1));
					}
					nextRun = 3;
					condition3.signalAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					lock.unlock();
				}
			}
			
		});
		
		Thread thread3 = new Thread(new Runnable(){

			@Override
			public void run() {
				try {
					lock.lock();
					while(nextRun != 3){
						condition3.await();
					}
					for(int i=0;i<3;i++){
						System.out.println("Thread3 "+(i+1));
					}
					nextRun = 1;
					condition1.signalAll();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}finally{
					lock.unlock();
				}
			}
			
		});
		
		Thread[] array1 = new Thread[5];
		Thread[] array2 = new Thread[5];
		Thread[] array3 = new Thread[5];
		
		for(int i=0;i<5;i++){
			array1[i] = new Thread(thread1);
			array2[i] = new Thread(thread2);
			array3[i] = new Thread(thread3);
			array1[i].start();
			array2[i].start();
			array3[i].start();
		}
	}
}

【执行结果如下】

Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3
Thread1 1
Thread1 2
Thread1 3
Thread2 1
Thread2 2
Thread2 3
Thread3 1
Thread3 2
Thread3 3

【读写锁ReentrantReadWriteLock】

读读共享、读写互斥、写写互斥

【读读共享】

package com.fyw.thread.lock;

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadReadLock {

	private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
	
	public void read(){
		try {
			readWriteLock.readLock().lock();
			System.out.println("线程"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"获得read锁");
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			readWriteLock.readLock().unlock();
		}
	}
	
	public static void main(String[] args) {
		ReadReadLock rrl = new ReadReadLock();
		ThreadA threadA = new ThreadA(rrl);
		threadA.setName("A");
		threadA.start();
		ThreadB threadB = new ThreadB(rrl);
		threadB.setName("B");
		threadB.start();
		
	}
}

【运行结果】

线程B并没有等到Asleep(10000)之后再执行,而是一起执行

线程A在1544972110700获得read锁
线程B在1544972110701获得read锁

读写、写写用法同上

你可能感兴趣的:(java并发编程)