Interface Lock
Lock lock = new ReentrantLock(); 无论需要同步的代码是不是在一个方法中,只要使用同一个锁对象就能实现同步(和synchronized原理一样)
//使用方法
try{
lock.lock();
同步代码...
} finally{
lock.unlock();
}
注意,多次重入需要多次释放:
thread.interrupt()
thread.interrupt();方法对lock.lock()没有用,线程不会中断也不会释放锁,会继续运行。
对lock.lockInterruptibly()则就会还是利用异常机制中断线程。
boolean tryLock(long timeout, TimeUnit unit)
boolean tryLock()就相当于没有等待时间
@Override
public void run() {
try {
if (lock.tryLock(2,TimeUnit.SECONDS)) {//等待两秒,如果还没得到🔒返回false
System.out.println(Thread.currentThread().getName() + "获得锁");
Thread.sleep(4000);
}else {
System.out.println(Thread.currentThread().getName() + "没有获得锁");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if(lock.isHeldByCurrentThread()){ //注意 要判断一下(避免没有得到锁的t2线程释放正在拿着锁运行的t1线程的锁)
lock.unlock();
}
}
}
Condition newCondition();
Interface Lock的优越性 => 更灵活
- 需要多少锁就new多少锁
- 需要锁哪些代码就锁哪些(即使代码不在一个方法中,用同一个锁就可以)
- 利用new多个condition对象,分类唤醒线程
// 进入等待
conditonA.await();
conditionB.await();
// 唤醒线程
conditionB.signal();//唤醒一个由conditionB进入等待的线程
conditionA.signalAll();//唤醒所有由conditionA进入等待的线程
- 可以实现公平锁
公平锁会按照时间顺序先到先得(使用完一次锁后就排到队尾)
synchronized内部锁是非公平锁
用构造方法ReentrantLock(boolean fair) 设置属性为true就会返回公平锁
公平锁缺点: 需要维护一个线程的有序队列,性能较低,只有特别要求才会使用。
ReentrantLock其他常用方法
getHoldCount()
Queries the number of holds on this lock by the current thread.
返回当前线程重入的次数(从0开始,lock()一次加一次,unlock()减一次,完全unlock()肯定就变成0了)
isHeldByCurrentThread()
判断当前线程是否持有该锁lock:
// 经常这样使用
if(lock.isHeldByCurrentThread()){
lock.unlock();
}
getQueueLength()
Returns an estimate of the number of threads waiting to acquire this lock.
返回等待获得锁的线程估数(锁池中的线程数)
getWaitQueueLength(Condition condition)
Returns an estimate of the number of threads waiting on the given condition associated with this lock.
返回由对应Condition放进等待池中的线程估数
hasQueuedThread(Thread thread)
Queries whether the given thread is waiting to acquire this lock.
hasQueuedThreads()
Queries whether any threads are waiting to acquire this lock.
hasWaiters(Condition condition)
Queries whether any threads are waiting on the given condition associated with this lock.(等待池)
isFair()
Returns true if this lock has fairness(公平) set true.
isLocked()
Queries if this lock is held by any thread.
Interface ReadWriteLock
实现类:ReentrantReadWriteLock
基本使用方法
线程组
- 子线程默认与父线程在同一线程组(如,main线程种创建一个线程,则该线程属于main线程组)
MyThread t1 = new MyThread();
System.out.println("t1线程组:" + t1.getThreadGroup());
//t1线程组:java.lang.ThreadGroup[name=main,maxpri=10]
- main方法中创建线程组,则该线程组的父线程组是main线程组
ThreadGroup group1 = new ThreadGroup("group1");
//java.lang.ThreadGroup[name=main,maxpri=10]
- 创建线程就可以指定线程组了
Thread t2 = new Thread(group1, r);
System.out.println("t2线程组:" + t2.getThreadGroup());
//t2线程组:java.lang.ThreadGroup[name=group1,maxpri=10]