Lock接口: void lock() 获取锁。 void unlock() 释放锁。 必须手动释放,放到finally中 实现类: ReentrantLock 可重入锁
通过Lock实现线程同步
public class Cave implements Runnable{
private Lock lock = new ReentrantLock();
@Override
public void run() {
lock.lock();
try {
String name = Thread.currentThread().getName();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+"通过山洞");
}finally {
lock.unlock();//必须手动释放
}
}
public static void main(String[] args) {
Cave cave = new Cave();
Thread[] array = new Thread[5];
for(int i=0; i<array.length; i++) {
array[i] = new Thread(cave, "火车"+(i+1));
}
for (Thread thread : array) {
thread.start();
}
}
}
通过Lock实现线程通信
Lock:
Condition newCondition()
返回绑定到此 Lock 实例的新 Condition 实例。
可以根据需要创建多个Condition对象
不同的情况使用不同的Condition对象来阻塞,更加清晰
Condition:
void await()
造成当前线程在接到信号或被中断之前一直处于等待状态。
void signal()
唤醒一个等待线程。
class Printer{
private int a = 0;
private Lock lock = new ReentrantLock();
//自己根据需要而定
private Condition numCondition = lock.newCondition();
private Condition caseCondition = lock.newCondition();
//对于同一个Printer对象的两个方法,在多线程中无法同时执行
public void printNum() {
lock.lock();
try {
//判断是否是先进来的,如果是先进来,等一等
if(a == 0) {
try {
//阻塞当前线程,锁暂时还回去
//继续的条件:
//1)通过当前对象在另外一个地方通过notify唤醒,2)并且再次获取到锁
numCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//1~26
for(int i=1; i<=26; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
caseCondition.signal();
try {
numCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}finally {
lock.unlock();
}
}
public void printCase() {
lock.lock();
try {
a = 1;
//A~Z
for(char c='A'; c<='Z';c++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(c);
//随机唤醒一个等待在该对象上的线程
numCondition.signal();
//等待输出一个数字之后再继续
try {
caseCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
numCondition.signal();
}finally {
lock.unlock();
}
}
}