1.ReentrantLock类的使用:
ReentrantLock类也能实现同步的效果,但是在扩展和功能上比synchronized更加强大
ReentrantLock对象的lock()方法获取锁,unlock()方法释放锁。
调用了lock()方法的线程持有了对象监视器,其他线程等有等待锁被释放的时候再争抢,使用效果和使用synchronized关键字一样,线程之间的执行顺序是随机的。
举个例子:
package com.wx.threadlearn7;
import java.sql.SQLOutput;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
private Lock lock=new ReentrantLock();
public void myMethod()
{
lock.lock();
for(int i=0;i<5;i++)
{
System.out.println(Thread.currentThread().getName()+" "+(i));
}
lock.unlock();
}
}
package com.wx.threadlearn7;
public class ThreadA extends Thread{
private MyService myService;
public ThreadA( MyService myService)
{
this.myService=myService;
}
@Override
public void run() {
myService.myMethod();
}
}
测试:
package com.wx.threadlearn7;
public class Test1 {
public static void main(String[] args)
{
MyService myService = new MyService();
ThreadA threadA1=new ThreadA(myService);
ThreadA threadA2=new ThreadA(myService);
ThreadA threadA3=new ThreadA(myService);
threadA1.start();
threadA2.start();
threadA3.start();
}
}
2.实现等待通知功能
使用关键字synchronized和wait()/notify()方法组合可以实现线程之间的通信,ReentrantLock类也可以,但是许需要借助Condition对象,在一个Lock对象中可以创建多个Condition对象,线程对象可以注册在指定的Condition中,从而可以有选择性的线程通知,这是他相比于synchronized最重要的一个功能。当然Condition在调用wait()方法之前也必须要先调用lock()方法拿到对象监视器,不然会报错。
package com.wx.threadlearn8;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
private ReentrantLock lock=new ReentrantLock();
private Condition condition=lock.newCondition();
public void waitmethod()
{
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+" awit()");
condition.await();
}catch (Exception e)
{
e.printStackTrace();
}finally {
lock.unlock();
System.out.println("锁被释放waitmethod");
}
}
public void signal()
{
try{
lock.lock();
System.out.println(Thread.currentThread().getName()+"signal");
condition.signal();
}
catch (Exception e)
{
e.printStackTrace();
}finally {
lock.unlock();
System.out.println("锁被释放signal");
}
}
}
package com.wx.threadlearn8;
public class ThreadA extends Thread {
private MyService myService;
public ThreadA(MyService myService)
{
this.myService=myService;
}
@Override
public void run() {
myService.waitmethod();
}
}
测试:
package com.wx.threadlearn8;
public class Test1 {
public static void main(String[] args)
{
try {
MyService myService=new MyService();
ThreadA threadA=new ThreadA(myService);
threadA.start();
Thread.sleep(3000);
//主线程来唤醒子线程
myService.signal();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
Object类中的wait()相当于Condition类中的await()方法
Object类中的notify()相当于Condition类中的signal()方法
Object类中的notifyAll()相当于Condition类中的signalAll()方法
3.如何唤醒指定的个线程?
package com.wx.threadlearn9;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
private ReentrantLock lock=new ReentrantLock();
private Condition conditionA=lock.newCondition();
private Condition conditionB=lock.newCondition();
public void awaitA()
{
try {
lock.lock();
System.out.println("await()A前");
conditionA.await();
System.out.println("await()A后");
}catch (Exception e)
{
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void awaitB()
{
try{
lock.lock();
System.out.println("await()B前");
conditionB.await();
System.out.println("await()B后");
}catch (Exception e)
{
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void signalA()
{
lock.lock();
System.out.println("唤醒A");
conditionA.signal();
lock.unlock();
}
public void signalB()
{
lock.lock();
System.out.println("唤醒B");
conditionB.signal();
lock.unlock();
}
}
线程A:
package com.wx.threadlearn9;
public class ThreadA extends Thread {
private MyService myService;
public ThreadA(MyService myService)
{
this.myService=myService;
}
@Override
public void run() {
myService.awaitA();
}
}
线程B:
package com.wx.threadlearn9;
public class ThreadB extends Thread {
private MyService myService;
public ThreadB(MyService myService)
{
this.myService=myService;
}
@Override
public void run() {
myService.awaitB();
}
}
测试:
package com.wx.threadlearn9;
public class Test {
public static void main(String[] args)
{
try {
MyService myService=new MyService();
ThreadA threadA=new ThreadA(myService);
threadA.start();
ThreadB threadB=new ThreadB(myService);
threadB.start();
Thread.sleep(3000);
myService.signalA();
Thread.sleep(3000);
myService.signalB();
}catch (Exception e)
{
e.printStackTrace();
}
}
}
4.实现生产者消费着交替打印
package com.wx.threadlearn10;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class MyService {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private boolean flag = false;
public void set() {
//生产者方法
try {
lock.lock();
while(flag==true) {
condition.await();
}
System.out.println("生产者方法");
flag = true;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void get() {
try {
lock.lock();
while(flag==false) {
condition.await();
}
System.out.println("消费者方法");
flag = false;
condition.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package com.wx.threadlearn10;
public class ThreadA extends Thread {
private MyService myService;
public ThreadA(MyService myService){
this.myService=myService;
}
@Override
public void run() {
while (true)
{
myService.set();
}
}
}
package com.wx.threadlearn10;
public class ThreadB extends Thread {
private MyService myService;
public ThreadB(MyService myService){
this.myService=myService;
}
@Override
public void run() {
while (true)
{
myService.get();
}
}
}
测试:
package com.wx.threadlearn10;
public class Test1 {
public static void main(String[] args) {
MyService myService = new MyService();
ThreadA threadA = new ThreadA(myService);
ThreadB threadB = new ThreadB(myService);
threadA.start();
threadB.start();
}
}
可以根据这个例子实现生产者消费者线程多对多的模式,即创建多个生产者和多个消费者即可。注意避免假死的状态出现。
4.公平锁和非公平锁
公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先进先出,而非公平锁就是一种获取锁的抢占机制,是随机获得锁的。