实现按顺序打印

一:题目描述
给你一个类:

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循环判正的话,导致死循环,无法推出。
所以设计成自旋判断为负,然后退出

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容