使用案例-两个线程交替执行
参考https://www.cnblogs.com/qingquanzi/p/8228422.html
线程间通信的经典案例,两个线程交替执行
private static Lock lock = new ReentrantLock();
private static Condition firstThreadCondition = lock.newCondition();
private static Condition secondThreadCondition = lock.newCondition();
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
/**
* 交替两个线程交替执行
*/
@Test
public void test() {
executorService.submit(new Runnable() {
@Override
public void run() {
while(true) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName());
//唤醒secondThreadCondition上的线程
secondThreadCondition.signal();
//释放锁、等待
firstThreadCondition.await();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
lock.unlock();
}
}
}
});
executorService.submit(new Runnable() {
@Override
public void run() {
while (true) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName());
//唤醒firstThreadCondition上的等待的线程
firstThreadCondition.signal();
//释放锁、等待
secondThreadCondition.await();
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
lock.unlock();
}
}
}
});
executorService.shutdown();
while (true){
if(executorService.isTerminated()){
break;
}
}
System.out.println("run over");
}
简单来说,就是第一个线程执行了然后在指定condition上的线程,然后当前线程释放锁,并且阻塞,另外一个线程获取到锁后,唤醒第一个线程所在条件变量,然后释放锁,并且阻塞。
ReentrantLock可重入测试
//-------------测试ReentrantLock可从入性--------------------
public static class TestPojo implements Runnable{
private static ReentrantLock reentrantLock=new ReentrantLock();
@Override
public void run() {
get();
}
public void get(){
reentrantLock.lock();
try{
System.out.println(Thread.currentThread().getId()+" get");
set();
}finally {
reentrantLock.unlock();
}
}
public void set(){
reentrantLock.lock();
try {
System.out.println(Thread.currentThread().getId()+" set");
}finally {
reentrantLock.unlock();
}
}
}
@Test
public void test01(){
new Thread(new TestPojo()).start();
while (Thread.activeCount()>2){
}
}
读写锁
需要说明的是加几把锁一定要释放指定的锁。
读-读不互斥:读读之间不阻塞
读-写互斥:读阻塞写,写也会阻塞读。
写-写互斥:写写阻塞。
测试代码
/**
* ReentrantReadWriteLock
*/
@Test
public void test08() throws InterruptedException {
ReentrantReadWriteLock lock= new ReentrantReadWriteLock();
Thread t01=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 尝试获取读锁");
lock.readLock().lock();
try{
System.out.println(Thread.currentThread().getName()+" 获取到读锁");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" 释放读锁");
lock.readLock().unlock();
}
}
});
t01.setName("t1");
t01.start();
Thread t02=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 尝试获取读锁");
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+" 获取到读锁");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" 释放读锁");
lock.readLock().unlock();
}
}
});
t02.setName("t2");
t02.start();
Thread t03=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 尝试获取写锁");
lock.writeLock().lock();
try{
System.out.println(Thread.currentThread().getName()+" 获取到写锁");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" 释放写锁");
lock.writeLock().unlock();
}
}
});
t03.setName("t3");
t03.start();
Thread t04=new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 尝试获取写锁");
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()+" 获取到写锁");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" 释放写锁");
lock.writeLock().unlock();
}
}
});
t04.setName("t4");
t04.start();
while (Thread.activeCount()>2){}
}