ReetrantLock类
ReetrantLock相比synchronized具有更加的灵活性。
public class MyService {
private Lock lock = new ReentrantLock();
public void testMethod() {
lock.lock();
for (int i = 0; i < 5; i++) {
System.out.println("ThreadName = " + Thread.currentThread().getName() + " " + (i + 1));
}
lock.unlock();
}
}
public class MyThread extends Thread {
/** Field service */
private MyService service;
/**
* Constructs MyThread
*
*
* @param service
*/
public MyThread(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.testMethod();
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
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);
MyThread a6 = new MyThread(service);
a1.start();
a2.start();
a3.start();
a4.start();
a5.start();
a6.start();
}
}
/*
ThreadName = Thread-1 1
ThreadName = Thread-1 2
ThreadName = Thread-1 3
ThreadName = Thread-1 4
ThreadName = Thread-1 5
ThreadName = Thread-0 1
ThreadName = Thread-0 2
ThreadName = Thread-0 3
ThreadName = Thread-0 4
ThreadName = Thread-0 5
ThreadName = Thread-2 1
ThreadName = Thread-2 2
ThreadName = Thread-2 3
ThreadName = Thread-2 4
ThreadName = Thread-2 5
ThreadName = Thread-3 1
ThreadName = Thread-3 2
ThreadName = Thread-3 3
ThreadName = Thread-3 4
ThreadName = Thread-3 5
ThreadName = Thread-4 1
ThreadName = Thread-4 2
ThreadName = Thread-4 3
ThreadName = Thread-4 4
ThreadName = Thread-4 5
ThreadName = Thread-5 1
ThreadName = Thread-5 2
ThreadName = Thread-5 3
ThreadName = Thread-5 4
ThreadName = Thread-5 5
*/
类ReetratantLock可以实现synchronized与wait()/notify()方法相结合的等待/通知模式。
类ReetratantLock需要借助Condition对象,实现多路通知。
Condition中的await()方法相当于Object()中的wait()方法。
Condition中的signal()方法相当于Object()中的notify()方法
public class MyService {
/** Field lock */
private Lock lock = new ReentrantLock();
/** Field condition */
public Condition condition = lock.newCondition();
/**
* Method await
*
*/
public void await() {
try {
lock.lock();
System.out.println(" await时间为 = " + System.currentTimeMillis());
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
try {
lock.lock();
System.out.println("signal 的时间为 = " + System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
public class ThreadA extends Thread {
/** Field service */
private MyService service;
/**
* Constructs ThreadA
*
*
* @param service
*/
public ThreadA(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.await();
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
Thread.sleep(3000);
service.signal();
}
}
/*result:
await时间为 = 1524378761637
signal 的时间为 = 1524378764638
*/
若想单独唤醒部分线程,则必须使用多个Condition对象,也就是Condition对象可以唤醒部分指定线程。有助于提高程序运行的效率。
可以先对线程分组,再唤醒指定组中线程。
public class MyService {
/** Field lock */
private Lock lock = new ReentrantLock();
/** Field conditionA */
public Condition conditionA = lock.newCondition();
/** Field conditionB */
public Condition conditionB = lock.newCondition();
/**
* Method awaitA
*
*/
public void awaitA() {
try {
lock.lock();
System.out.println("begin awaitA 时间为; " + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
conditionA.await();
System.out.println(" end awaitA 时间为; " + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* Method awaitB
*
*/
public void awaitB() {
try {
lock.lock();
System.out.println("begin awaitB 时间为; " + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
conditionB.await();
System.out.println(" end awaitB 时间为; " + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* Method signalAll_A
*
*/
public void signalAll_A() {
try {
lock.lock();
System.out.println(" begin siginAll时间为:" + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
conditionA.signalAll();
System.out.println(" end siginalAll时间为:" + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
/**
* Method signalAll_B
*
*/
public void signalAll_B() {
try {
lock.lock();
System.out.println(" begin siginAll时间为:" + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
conditionB.signalAll();
System.out.println(" end siginalAll时间为:" + System.currentTimeMillis() + " ThreadName = "
+ Thread.currentThread().getName());
} finally {
lock.unlock();
}
}
}
public class ThreadA extends Thread {
/** Field service */
private MyService service;
/**
* Constructs ThreadA
*
*
* @param service
*/
public ThreadA(MyService service) {
super();
this.service = service;
}
/**
* Method run
*
*/
public void run() {
service.awaitA();
}
}
public class ThreadB extends Thread {
/** Field service */
private MyService service;
/**
* Constructs ThreadB
*
*
* @param service
*/
public ThreadB(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
service.awaitB();
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
MyService service = new MyService();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
Thread.sleep(3000);
service.signalAll_A();
}
}
/*result:
begin awaitB 时间为; 1524381997080 ThreadName = B
begin awaitA 时间为; 1524381997082 ThreadName = A
begin siginAll时间为:1524382000081 ThreadName = main
end siginalAll时间为:1524382000081 ThreadName = main
end awaitA 时间为; 1524382000081 ThreadName = A
*/
由此实验可知使用ReentrantLock对象可以唤醒指定种类的线程,这是控制部分新城行为的方便方式。
实现生产者/消费者模式,一对一交替打印
public class MyService {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/** Field condition */
private Condition condition = lock.newCondition();
/** Field hasValue */
private Boolean hasValue = false;
/**
* Method get
*
*/
public void get() {
try {
lock.lock();
while (!hasValue) {
condition.await();
}
System.out.println("打印☆");
hasValue = false;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* Method set
*
*/
public void set() {
try {
lock.lock();
while (hasValue) {
condition.await();
}
System.out.println("打印★");
hasValue = true;
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class MyThreadA extends Thread {
/** Field service */
private MyService service;
/**
* Constructs MyThreadA
*
*
* @param service
*/
public MyThreadA(MyService service) {
this.service = service;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
service.set();
}
}
}
public class MyThreadB extends Thread {
/** Field service */
private MyService service;
/**
* Constructs MyThreadB
*
*
* @param service
*/
public MyThreadB(MyService service) {
super();
this.service = service;
}
@Override
public void run() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
service.get();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
MyService service = new MyService();
MyThreadA a = new MyThreadA(service);
a.start();
MyThreadB b = new MyThreadB(service);
b.start();
}
}
/*result:
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
打印★
打印☆
... ...
*/
公平锁和非公平锁
锁Lock分为"公平锁"和"非公平锁"。
公平锁表示西安获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO先进先出顺序。
非公平锁就是一种获取锁的抢占机制,是随机获得的锁,可能造成某些线程长期拿不到锁,结果就是不公平的。
public class Service {
/** Field lock */
private ReentrantLock lock;
/**
* Constructs Service
*
*
* @param isFair
*/
public Service(boolean isFair) {
super();
lock = new ReentrantLock(isFair);
}
/**
* Method serviceMethod
*
*/
public void serviceMethod() {
try {
lock.lock();
System.out.println("ThreadName = " + Thread.currentThread().getName() + "获得锁定");
} finally {
lock.unlock();
}
}
}
public class RunFair {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final Service service = new Service(true);
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("★线程 " + Thread.currentThread().getName() + " 运行了");
service.serviceMethod();
}
};
Thread[] threadArray = new Thread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}
/*result:
★线程 Thread-0 运行了
★线程 Thread-5 运行了
★线程 Thread-1 运行了
★线程 Thread-6 运行了
ThreadName = Thread-0获得锁定
★线程 Thread-9 运行了
★线程 Thread-8 运行了
★线程 Thread-3 运行了
★线程 Thread-2 运行了
★线程 Thread-4 运行了
★线程 Thread-7 运行了
ThreadName = Thread-5获得锁定
ThreadName = Thread-1获得锁定
ThreadName = Thread-6获得锁定
ThreadName = Thread-9获得锁定
ThreadName = Thread-8获得锁定
ThreadName = Thread-3获得锁定
ThreadName = Thread-2获得锁定
ThreadName = Thread-4获得锁定
ThreadName = Thread-7获得锁定
*/
public class RunNotFair {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final Service service = new Service(false);
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("★线程 " + Thread.currentThread().getName() + " 运行了");
service.serviceMethod();
}
};
Thread[] threadArray = new Thread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
}
}
/*result:
★线程 Thread-1 运行了
★线程 Thread-4 运行了
★线程 Thread-5 运行了
★线程 Thread-8 运行了
★线程 Thread-0 运行了
ThreadName = Thread-1获得锁定
★线程 Thread-9 运行了
ThreadName = Thread-4获得锁定
ThreadName = Thread-5获得锁定
ThreadName = Thread-8获得锁定
ThreadName = Thread-0获得锁定
ThreadName = Thread-9获得锁定
★线程 Thread-2 运行了
ThreadName = Thread-2获得锁定
★线程 Thread-3 运行了
ThreadName = Thread-3获得锁定
★线程 Thread-6 运行了
ThreadName = Thread-6获得锁定
★线程 Thread-7 运行了
ThreadName = Thread-7获得锁定
*/
getHoldCount()方法
int getHoldCount()方法是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/**
* Method serviceMethod1
*
*/
public void serviceMethod1() {
try {
lock.lock();
System.out.println("serviceMethod1 getHoldCount = " + lock.getHoldCount());
serviceMethod2();
} finally {
lock.unlock();
}
}
/**
* Method serviceMethod2
*
*/
public void serviceMethod2() {
try {
lock.lock();
System.out.println("serviceMethod2 getHoldCount = " + lock.getHoldCount());
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
Service service = new Service();
service.serviceMethod1();
}
}
/*
serviceMethod1 getHoldCount = 1
serviceMethod2 getHoldCount = 2
*/
getQueueLength()方法
int getQueueLength()方法的作用是返回正等待获取此锁定的线程估计数。
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
public ReentrantLock getLock() {
return lock;
}
public void setLock(ReentrantLock lock) {
this.lock = lock;
}
/**
* Method serviceMethod1
*
*/
public void serviceMethod1() {
try {
lock.lock();
System.out.println("ThreadName = " + Thread.currentThread().getName() + "进入方法");
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final Service service = new Service();
Runnable runnable = new Runnable() {
@Override
public void run() {
service.serviceMethod1();
}
};
Thread[] threadArray = new Thread[10];
for (int i = 0; i < 10; i++) {
threadArray[i] = new Thread(runnable);
}
for (int i = 0; i < 10; i++) {
threadArray[i].start();
}
Thread.sleep(2000);
System.out.println("有线程数:" + service.getLock().getQueueLength() + " 在等待线程!");
}
}
/*result:
ThreadName = Thread-0进入方法
有线程数:9 在等待线程!
*/
getWaitQueueLength()方法
int getWaitQueueLength(Condition condition)方法,作用是返回等待与此锁定相关的给定条件Condition的线程估计数。
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/** Field condition */
private Condition condition = lock.newCondition();
/**
* Method notifyMethod
*
*/
public void notifyMethod() {
try {
lock.lock();
System.out.println("有 " + lock.getWaitQueueLength(condition) + "个线程正在等待");
condition.signalAll();
} finally {
lock.unlock();
}
}
/**
* Method waitMethod
*
*/
public void waitMethod() {
try {
lock.lock();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final Service service = new Service();
Runnable runnable = new Runnable() {
@Override
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();
}
}
/*result:
有 10个线程正在等待
*/
hasQueuedThread()方法
方法boolean hasQueuedThread(Thread thread)的作用是查询是指定的线程是否正在等待。
hasQueuedThreads()方法
方法boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁定。
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/** Field condition */
private Condition condition = lock.newCondition();
/**
* Method waitMethod
*
*/
public void waitMethod() {
try {
lock.lock();
Thread.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
/**
* Method getCondition
*
*
* @return
*/
public Condition getCondition() {
return condition;
}
/**
* Method setCondition
*
*
* @param condition
*/
public void setCondition(Condition condition) {
this.condition = condition;
}
/**
* Method getLock
*
*
* @return
*/
public ReentrantLock getLock() {
return lock;
}
/**
* Method setLock
*
*
* @param lock
*/
public void setLock(ReentrantLock lock) {
this.lock = lock;
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final Service service = new Service();
Runnable runnable = new Runnable() {
@Override
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.getLock().hasQueuedThread(threadA));
System.out.println(service.getLock().hasQueuedThread(threadB));
System.out.println(service.getLock().hasQueuedThreads());
}
}
/*result:
false
true
true
*/
hasWaiters()方法
方法boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的Codition
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/** Field condition */
private Condition condition = lock.newCondition();
/**
* Method notifyMethod
*
*/
public void notifyMethod() {
try {
lock.lock();
System.out.println(" 有没有线程正在等待condition? " + lock.hasWaiters(condition) + " 线程数是多少? "
+ lock.getWaitQueueLength(condition));
condition.signal();
} finally {
lock.unlock();
}
}
/**
* Method waitMethod
*
*/
public void waitMethod() {
try {
lock.lock();
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final Service service = new Service();
Runnable runnable = new Runnable() {
@Override
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();
}
}
/*result:
有没有线程正在等待condition? true 线程数是多少? 10
*/
方法isFair(), isHeldByCurrentThread()和isLocked()
- 方法boolean isFair()的作用是判断是不是公平锁.默认情况ReentrantLock是非公平锁。
public class Service {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/**
* Constructs Service
*
*
* @param isFair
*/
public Service(Boolean isFair) {
super();
lock = new ReentrantLock(isFair);
}
/**
* Method serviceMethod
*
*/
public void serviceMethod() {
try {
lock.lock();
System.out.println("公平锁情况:" + lock.isFair());
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final Service service1 = new Service(true);
Runnable runnable = new Runnable() {
@Override
public void run() {
service1.serviceMethod();
}
};
Thread thread = new Thread(runnable);
thread.start();
final Service service2 = new Service(false);
runnable = new Runnable() {
@Override
public void run() {
service2.serviceMethod();
}
};
thread = new Thread(runnable);
thread.start();
}
}
/*result:
公平锁情况:true
公平锁情况:false
*/
Boolean isHeldByCurrentThread()方法作用是判断当前线程是否锁定。
public class Service {
/** Field lock */
private ReentrantLock lock;
/**
* Constructs Service
*
*
* @param isFair
*/
public Service(Boolean isFair) {
super();
lock = new ReentrantLock(isFair);
}
/**
* Method serviceMethod
*
*/
public void serviceMethod() {
try {
System.out.println(lock.isHeldByCurrentThread());
lock.lock();
System.out.println(lock.isHeldByCurrentThread());
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final Service service1 = new Service(true);
Runnable runnable = new Runnable() {
@Override
public void run() {
service1.serviceMethod();
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
/*
false
true
*/
boolean isLocked()方法作用是判断是是否有线程获得该锁定。
public class Service {
/** Field lock */
private ReentrantLock lock;
/**
* Constructs Service
*
*
* @param isFair
*/
public Service(Boolean isFair) {
super();
lock = new ReentrantLock(isFair);
}
/**
* Method serviceMethod
*
*/
public void serviceMethod() {
try {
System.out.println(lock.isLocked());
lock.lock();
System.out.println(lock.isLocked());
} finally {
lock.unlock();
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final Service service1 = new Service(true);
Runnable runnable = new Runnable() {
@Override
public void run() {
service1.serviceMethod();
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
/*result:
false
true
*/
方法lockInterruptibly()
方法 void lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断,则出现异常。
public class MyService {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/** Field condition */
private Condition condition = lock.newCondition();
/**
* Method waitMethod
*
*/
public void waitMethod() {
try {
// lock.lock();
lock.lockInterruptibly();
System.out.println("lock begin " + Thread.currentThread().getName());
for (int i = 0; i < Integer.MAX_VALUE / 10; i++) {
String newString = new String();
Math.random();
}
System.out.println("lock end " + Thread.currentThread().getName());
} catch (InterruptedException e) {
System.out.println("抛异常方法是:" + Thread.currentThread().getName());
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A");
threadA.start();
Thread.sleep(500);
Thread threadB = new Thread(runnableRef);
threadB.setName("B");
threadB.start();
threadB.interrupt(); // 打标记
}
}
/*
lock begin A
抛异常方法是:B
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at com.tz4.lockInterruptiblyTest.MyService.waitMethod(MyService.java:24)
at com.tz4.lockInterruptiblyTest.Run$1.run(Run.java:21)
at java.lang.Thread.run(Thread.java:745)
lock end A
*/
方法tryLock()
boolean tryLock()方法的作用是,仅在调用时锁定未被另一个线程保持的状况下,才获取锁定。
public class MyService {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/**
* Method waitMethod
*
*/
public void waitMethod() {
if (lock.tryLock()) {
System.out.println(Thread.currentThread().getName() + " 加锁");
} else {
System.out.println(Thread.currentThread().getName() + " 未加锁");
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A ");
threadA.start();
Thread threadB = new Thread(runnableRef);
threadB.setName("B ");
threadB.start();
}
}
/*result:
A 加锁
B 未加锁
*/
方法tryLock(long timeout, TimeUnit unit)
boolean tryLock(long timeout, TimeUnit unit)方法的作用是,如果锁定在给定等待时间内没有被另一个线程保持,且当前线程未被中断,则获得锁定。
public class MyService {
/** Field lock */
private ReentrantLock lock = new ReentrantLock();
/**
* Method waitMethod
*
*/
public void waitMethod() {
try {
if (lock.tryLock(3, TimeUnit.SECONDS)) {
System.out.println(" " + Thread.currentThread().getName() + "获得锁的时间: "
+ System.currentTimeMillis());
//Thread.sleep(10000);
Thread.sleep(100);
} else {
System.out.println(" " + Thread.currentThread().getName() + "未获得锁");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
final MyService service = new MyService();
Runnable runnableRef = new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "调用waitMethod时间: " + System.currentTimeMillis());
service.waitMethod();
}
};
Thread threadA = new Thread(runnableRef);
threadA.setName("A ");
threadA.start();
Thread threadB = new Thread(runnableRef);
threadB.setName("B ");
threadB.start();
}
}
/*result:
B 调用waitMethod时间: 1525003358344
A 调用waitMethod时间: 1525003358344
A 获得锁的时间: 1525003358345
B 未获得锁
*/
/*result:
A 调用waitMethod时间: 1525003544000
B 调用waitMethod时间: 1525003544000
B 获得锁的时间: 1525003544001
A 获得锁的时间: 1525003544101
*/
使用Condition实现顺序执行
使用Condition对象对线程执行的业务进行顺序规划。
public class F {
/** Field nextPrintWho */
public static volatile int nextPrintWho = 1;
}
public class Run {
/** Field nextPrintWho */
private static volatile int nextPrintWho = 1;
/** Field lock */
private static ReentrantLock lock = new ReentrantLock();
/** Field conditionA */
private static final Condition conditionA = lock.newCondition();
/** Field conditionB */
private static final Condition conditionB = lock.newCondition();
/** Field conditionC */
private static final Condition conditionC = lock.newCondition();
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
Thread threadA = new Thread() {
public void run() {
try {
lock.lock();
while (nextPrintWho != 1) {
conditionA.await();
}
for (int i = 0; i < 3; i++) {
System.out.println("ThreadA " + (i + 1));
}
nextPrintWho = 2;
conditionB.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
Thread threadB = new Thread() {
public void run() {
try {
lock.lock();
while (nextPrintWho != 2) {
conditionB.await();
}
for (int i = 0; i < 3; i++) {
System.out.println("ThtradB " + (i + 1));
}
nextPrintWho = 3;
conditionC.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
Thread threadC = new Thread() {
public void run() {
try {
lock.lock();
while (nextPrintWho != 3) {
conditionC.await();
}
for (int i = 0; i < 3; i++) {
System.out.println("ThreadC " + (i + 1));
}
nextPrintWho = 1;
conditionA.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
Thread[] aArray = new Thread[5];
Thread[] bArray = new Thread[5];
Thread[] cArray = new Thread[5];
for (int i = 0; i < 5; i++) {
aArray[i] = new Thread(threadA);
bArray[i] = new Thread(threadB);
cArray[i] = new Thread(threadC);
aArray[i].start();
bArray[i].start();
cArray[i].start();
}
}
}
/*result:
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
ThreadA 1
ThreadA 2
ThreadA 3
ThtradB 1
ThtradB 2
ThtradB 3
ThreadC 1
ThreadC 2
ThreadC 3
*/
ReentrantReadWriteLock类
ReentrantLock()锁具有完全互斥的性质,同一时间只有一个线程可以获得锁。
而ReentrantReadWriteLock锁表示俩锁,一个是读锁也叫共享锁,另一个是写锁,也叫排它锁。可以提高线程读写效率。
public class Service {
/** Field lock */
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/**
* Method read
*
*/
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("获得读锁!" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.readLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
/** Field service */
private Service service;
/**
* Constructs ThreadA
*
*
* @param service
*/
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.read();
}
}
public class ThreadB extends Thread {
/** Field service */
private Service service;
/**
* Constructs ThreadB
*
*
* @param service
*/
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.read();
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
}
}
/*result:
获得读锁!A 1525253407220
获得读锁!B 1525253407220
*/
A,B线程几乎同时获得读锁,同时运行,应用了共享锁。也就是读读共享
public class Service {
/** Field lock */
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/**
* Method write
*
*/
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("数据写入" + Thread.currentThread().getName() + " " + System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.writeLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
/** Field service */
private Service service;
/**
* Constructs ThreadA
*
*
* @param service
*/
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.write();
}
}
public class ThreadB extends Thread {
/** Field service */
private Service service;
/**
* Constructs ThreadB
*
*
* @param service
*/
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.write();
}
}
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
ThreadB b = new ThreadB(service);
b.setName("B");
a.start();
b.start();
}
}
/*reslut:
数据写入B 1525260900544
数据写入A 1525260910545
*/
写锁互斥了,使用排他锁就线程间是互斥关系,同一时间只有一个线程可以获得写锁。
还有读写互斥和写读互斥的情况,可以灵活运用。