一:题目描述
给你一个类:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
三个不同的线程 A、B、C 将会共用一个 Foo 实例。
线程 A 将会调用 first() 方法
线程 B 将会调用 second() 方法
线程 C 将会调用 third() 方法
请设计修改程序,以确保 second() 方法在 first() 方法之后被执行,third() 方法在 second() 方法之后被执行。·
二:算法设计
首先初始化共享变量 firstJobDone 和 secondJobDone,初始值表示所有方法未执行。
方法 first() 没有依赖关系,可以直接执行。在方法最后更新变量 firstJobDone 表示该方法执行完成。
方法 second() 中,检查 firstJobDone 的状态。如果未更新则进入等待状态,否则执行方法 second()。在方法末尾,更新变量 secondJobDone 表示方法 second() 执行完成。
方法 third() 中,检查 secondJobDone 的状态。与方法 second() 类似,执行 third() 之前,需要先等待 secondJobDone 的状态。
三:代码实现1
class Foo {
private AtomicInteger firstJobDone = new AtomicInteger(0);
private AtomicInteger secondJobDone = new AtomicInteger(0);
public Foo() {
}
public void first(Runnable printFirst) throws InterruptedException {
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
firstJobDone.incrementAndGet();
}
public void second(Runnable printSecond) throws InterruptedException {
while (!(firstJobDone.compareAndSet(1, 0))) {
}
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
secondJobDone.incrementAndGet();
}
public void third(Runnable printThird) throws InterruptedException {
while (!(secondJobDone.compareAndSet(1, 0))) {
}
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
}
}
代码实现2:
public class PrintABCWithAtomicInteger {
private static final Logger log = LoggerFactory.getLogger(PrintABCWithAtomicInteger.class);
private int times;
private volatile int state;
private static AtomicInteger atomicState = new AtomicInteger(0);
private static final Object LOCK = new Object();
public PrintABCWithAtomicInteger(int times){
this.times = times;
}
public void printA() {
try {
print("A", 0);
}catch (Exception e){
log.error(e.getMessage());
}
}
public void printB() {
try {
print("B", 1);
}catch(Exception e){
log.error(e.getMessage());
};
}
public void printC() {
try {
print("C", 2);
}catch(Exception e){
log.error(e.getMessage());
};
}
public void print(String name, int targetState) throws InterruptedException {
for(int i = 0; i < times; i++){
while(atomicState.get() % 3 != targetState){
}
System.out.println(name);
atomicState.incrementAndGet();
}
}
public static void main(String[] args){
PrintABCWithAtomicInteger printABCWithAtomicInteger = new PrintABCWithAtomicInteger(10);
ExecutorService pool = Executors.newFixedThreadPool(3);
for(int i = 0; i < 3; i++){
try {
pool.submit(new Thread(printABCWithAtomicInteger::printA));
pool.submit(new Thread(printABCWithAtomicInteger::printB));
pool.submit(new Thread(printABCWithAtomicInteger::printC));
}catch (Exception e){
log.error(e.getMessage());
}
}
}
}
四:AtomicInteger原理
class CASLock {
AtomicInteger atomicInteger = new AtomicInteger();
Thread currentThread = null;
public void tryLock() throws Exception{
boolean isLock = atomicInteger.compareAndSet(0, 1);
if(!isLock){
throw new Exception("加锁失败");
}
currentThread = Thread.currentThread();
System.out.println(currentThread + " tryLock");
}
public void unlock() {
int lockValue = atomicInteger.get();
if(lockValue == 0){
return;
}
if(currentThread == Thread.currentThread()){
atomicInteger.compareAndSet(1,0);
System.out.println(currentThread + " unlock");
}
}
public static void main(String[] args) {
CASLock casLock = new CASLock();
for(int i = 0;i < 5;i++){
new Thread(() -> {
try {
casLock.tryLock();
Thread.sleep(10000);
} catch (Exception e) {
e.printStackTrace();
}finally {
casLock.unlock();
}
}).start();
}
}
}
new Runnable原理
四:踩坑记录
1 内存不足
使用countDownLatch导致内存不足。
2 超出时间限制
while循环判正的话,导致死循环,无法推出。
所以设计成自旋判断为负,然后退出