文章目录
使用Reentrantlock 类
使用Reentrantlock 实现同步
package ReentrantLockTest;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author
* @create 2020-11-19 14:41
**/
public class MyService {
private Lock lock = new ReentrantLock();
public void testMethod() {
lock.lock();
for (int i = 0; i < 5; i++) {
System.out.println("ThreadNmae=" + Thread.currentThread().getName() +
(" " + (i +1)));
}
lock.unlock();
}
}
package ReentrantLockTest;
/**
* @author
* @create 2020-11-19 14:46
**/
public class MyThread extends Thread {
private MyService service;
public MyThread(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.testMethod();
}
}
package ReentrantLockTest;
/**
* @author
* @create 2020-11-19 14:48
**/
public class Run {
public static void main(String[] args) {
MyService service = new MyService();
MyThread a1 = new MyThread(service);
MyThread a2 = new MyThread(service);
MyThread a3 = new MyThread(service);
MyThread a4 = new MyThread(service);
MyThread a5 = new MyThread(service);
a1.start();
a2.start();
a3.start();
a4.start();
a5.start();
}
}
运行结果
结果可以看出
1 Reentrantlock对象的lock 方法获取锁,调用unlock 方法释放锁。
2 每个线程都是打印完成后释放锁,其他的线程继续打印。
3 线程之间的打印顺序是随机的。
使用ReentrantLock 实现同步 测试2
package ConditionTestMoreMethod;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author
* @create 2020-11-19 15:00
**/
public class MyService {
private Lock lock = new ReentrantLock();
public void methodA() {
try {
lock.lock();
System.out.println("methodA begin ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("methodA end ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
public void methodB() {
try {
lock.lock();
System.out.println("methodB begin ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
Thread.sleep(5000);
System.out.println("methodB end ThreadName=" + Thread.currentThread().getName() + " time= " + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
finally {
lock.unlock();
}
}
}
package ConditionTestMoreMethod;
/**
* @author
* @create 2020-11-19 15:05
**/
public class ThreadA extends Thread {
private MyService service;
public ThreadA(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.methodA();
}
}
package ConditionTestMoreMethod;
/**
* @author
* @create 2020-11-19 15:07
**/
public class ThreadAA extends Thread{
private MyService service;
public ThreadAA(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.methodA();
}
}
package ConditionTestMoreMethod;
/**
* @author
* @create 2020-11-19 15:07
**/
public class ThreadB extends Thread {
private MyService service;
public ThreadB(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.methodB();
}
}
package ConditionTestMoreMethod;
/**
* @author
* @create 2020-11-19 15:07
**/
public class ThreadBB extends Thread{
private MyService service;
public ThreadBB(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.methodB();
}
}
package ConditionTestMoreMethod;
/**
* @author
* @create 2020-11-19 15:09
**/
public class Run {
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadA aa = new ThreadA(service);
aa.setName("AA");
aa.start();
Thread.sleep(100);
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
ThreadBB bb = new ThreadBB(service);
bb.setName("BB");
bb.start();
}
}
1 调用 lock.lock()这个代码的线程持有了“”对象监视器“”,其他线程只能等待锁被释放时,再次争抢。
2 效果和使用synchronized关键字是一样的。线程之间还是顺序执行的。
使用condition 实现等待/通知
1 关键字 synchronized 与 wait() 和 notify() / notifyAll() 方法相结合可以实现等待/通知模式。
2 类ReentrantLock 结合 Condition 对象 可以实现同样的功能。
3 Lock对象可以创建多个Condition 对象监视器 实例,线程对象可以注册在指定的condition 中,从而有选择的进行某一类的线程通知。调度更加灵活。
区别
- notify 、和notifyAll 方法进行通知的时候,被通知的线程却是由JVM 随机选择的。但是ReentrantLock 结合 condition 类是可以实现前面介绍过的“”选择性通知“”
- synchronized 就相当于整个的Lock 对象中只有一个单一的Condition对象。所有的线程都注册在一个对象身上。notifyAll()方法调用的时候,会通知所有的waiting的线程。没有选择权,效率很低。
package UseConditionWaitNotifyError;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author
* @create 2020-11-19 15:37
**/
public class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await() {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package UseConditionWaitNotifyError;
/**
* @author
* @create 2020-11-19 15:43
**/
public class ThreadA extends Thread{
private MyService service;
public ThreadA(MyService service) {
super();
this.service= service;
}
@Override
public void run() {
service.await();
}
}
package UseConditionWaitNotifyError;
/**
* @author
* @create 2020-11-19 15:44
**/
public class Run {
public static void main(String[] args) {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.start();
}
}
报错异常信息是监视器出错,解决办法是必须在condition.await()方法调用之前调用lock.lock()代码获得同步监视器。
package UseConditionWaitNotifyOk;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author
* @create 2020-11-19 15:50
**/
public class MyService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void waitMethod() {
try {
lock.lock();
System.out.println("A");
condition.await();
System.out.println("B");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.out.println("锁被释放了! ");
}
}
}
这里线程调用了 Condition 对象的await() 方法,是当前执行的任务的线程进入了等待,waiting 状态。
正确使用Condition 实现等待/通知
使用 Condition 类中的await方法实现 等待通知机制
Object 类中的wait() 方法相当于Condition 类中的 await()方法、
Object类中的wait(long timeout) 方法 相当于 Condition 中的 awat(long timeout,TimeUnit unit) 方法。
Object 类中的notify()方法相当于Condition类中的signal()方法。
Object 类中的notifyAll() 方法相当于Condition类中的signalAll() 方法