迅雷笔试题:
编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
解决思路:每个线程运行时先检查他依赖的线程是否已完成工作,线程B依赖线程A的完成,线程C依赖线程B和线程A的完成,线程A依赖线程C的完成。如果当前线程依赖的线程没有执行完,则阻塞当前线程直到条件满足再执行。
Condition.await()会使当前线程暂时阻塞,并释放ReentrantLock锁.
Condition.signalAll()会通知激活Condition.await()而阻塞的线程,这时被激活的线程就会继续检查(通过while循环))是否满足条件,如果满足而且再次获得ReentrantLock锁就能继续运行,否则继续等待。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; public class ThreadDemo implements Runnable { private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
//标记线程A的状态,true为刚执行完。为什么要两个变量?因为只使用一个变量,当线程A执行完后,a为true,B线程就会不停执行
//所以线程B执行要执行必须满足a==true&&a2==true
private volatile Boolean a = false, a2 = false;
//标记线程B的状态,true为刚执行完。
private volatile Boolean b = false;
//标记线程C的状态,true为刚执行完。
private volatile Boolean c = true; @Override
public void run() {
String name = Thread.currentThread().getName();
lock.lock();
//进入临界区
try {
for (int i = 0; i < 10; i++) {
if (name.equals("B")) {
//只有a和a2同时为true时才打印B,否则阻塞当前线程
while (!a || !a2) {
condition.await();//条件不满足,暂时阻塞线程,暂时释放lock
}
b = true;
a2 = false;
} else if (name.equals("C")) {
while (!a || !b) {
condition.await();
}
c = true;
b = false;
} else if (name.equals("A")) {
while (!c) {
condition.await();
}
a = true;
a2 = true;
b = false;
c = false;
}
System.out.print(name);
condition.signalAll();//通知正在等待的线程,此时有可能已经满足条件
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();// 记得要释放锁
}
} public static void main(String[] args) throws InterruptedException {
ThreadDemo task = new ThreadDemo();
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
Thread thread3 = new Thread(task);
thread1.setName("A");
thread2.setName("B");
thread3.setName("C");
thread1.start();
thread2.start();
thread3.start();
} }
下面是更简单的实现方法:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; public class ThreadDemo implements Runnable { private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int state = 0; @Override
public void run() {
String name = Thread.currentThread().getName();
lock.lock();
// 进入临界区
try {
for (int i = 0; i < 10; i++) {
if (name.equals("B")) {
// 只有a和a2同时为true时才打印B,否则阻塞当前线程
while (state % 3 != 1) {
condition.await();// 条件不满足,暂时阻塞线程,暂时释放lock
}
} else if (name.equals("C")) {
while (state % 3 != 2) {
condition.await();
}
} else if (name.equals("A")) {
while (state % 3 != 0) {
condition.await();
}
}
state++;
System.out.print(name);
condition.signalAll();// 通知正在等待的线程,此时有可能已经满足条件
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();// 记得要释放锁
}
} public static void main(String[] args) throws InterruptedException {
ThreadDemo task = new ThreadDemo();
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
Thread thread3 = new Thread(task);
thread1.setName("A");
thread2.setName("B");
thread3.setName("C");
thread1.start();
thread2.start();
thread3.start();
} }