还有老题Event/Fire多线程。详细题目解释可以参考:https://www.evernote.com/shard/s ... 906d67ab4ea189304f1
大意就是一个timeline上,event里面有两个method, 一个是register一个是fire,然后不停有Callback cb进来,register就一直把cb存起来,但是当call了fire这个method,先把之前所有register的event全部执行一遍,而且从此以后register不在存cb,而是直接运行当前传进来的cb. From 1point 3acres bbs
先来单线程
class CallBack {
        String name;

        public CallBack() {
        }

        public CallBack(String name) {
                this.name = name;
        }

        public void call() {
                System.out.println("CallBack Event " + this.name + "is running now");
        }
}

不用担心callback class,他给了这个class,我只是为了自己测试。看下面就好了

public class EventFire {
        Queue<CallBack> eventQueue = new LinkedList<>();
        boolean isFired = false;

        public void reg_cb(CallBack cb) {
                if (!isFired) {
                        eventQueue.offer(cb);
                }
                else {
                        cb.call();
                }
        }

        public void fire() {
                while (!eventQueue.isEmpty()) {
                        eventQueue.poll().call();
                }

                isFired = true;
        }

}

然后继续,实现thread safe,先问了把isFired = true放在前面有什么好处。然后就是第二个版本
public class EventFire {
        Queue<CallBack> eventQueue = new LinkedList<>();
        boolean isFired = false;
        Lock lock;

        public void reg_cb(CallBack cb) {
                lock.lock();
                if (!isFired) {
                        eventQueue.offer(cb);
                        lock.unlock();
                }
                else {
                        lock.unlock();
                        cb.call();
                }
        }

        public void fire() {
                lock.lock();
                isFired = true;
                while (!eventQueue.isEmpty()) {
                        CallBack cb = eventQueue.poll();
                        lock.unlock();  // could register when callback is running
                        cb.call();
                        lock.lock();
                }
                lock.unlock();
        }
}

然后walk through了一遍code和所有的锁,问了每一种情况(真的是每一种,加和不加有什么区别,有什么风险,千万不要紧张,一紧张就直接晕了)
然后ok,开始把锅扔给intership, 说现在有一个intership想优化code,写了第三个版本:
public class EventFire {
        Queue<CallBack> eventQueue = new LinkedList<>();
        boolean isFired = false;
        Lock lock;

        public void reg_cb(CallBack cb) {
                lock.lock();
                if (!isFired) {
                        eventQueue.offer(cb);
                        lock.unlock();
                }
                else {
                        lock.unlock();
                        cb.call();
                }
        }

        public void fire() {
                lock.lock();
                isFired = true;
                lock.unlock();

                while (!eventQueue.isEmpty()) {
                        CallBack cb = eventQueue.poll();
                        cb.call();
                }
        }
}

有什么区别,有没有风险,然后walk through了一遍,然后这个intership还改, 第四个版本:
public class EventFire {
        Queue<CallBack> eventQueue = new LinkedList<>();
        boolean isFired = false;
        Lock lock;

        public void reg_cb(CallBack cb) {
                lock.lock();
                if (!isFired) {
                        eventQueue.offer(cb);
                        lock.unlock();
                }
                else {
                        lock.unlock();
                        cb.call();
                }
        }

        public void fire() {
                lock.lock();
                lock.unlock();
                isFired = true;
                while (!eventQueue.isEmpty()) {
                        CallBack cb = eventQueue.poll();
                        cb.call();
                }
        }
}

问有没有风险,当然有风险,锁和没锁一样的。然后继续改,第五个版本:
public class EventFire {
        Queue<CallBack> eventQueue = new LinkedList<>();
        boolean isFired = false;
        Lock lock;

        public void reg_cb(CallBack cb) {
                lock.lock();
                if (!isFired) {
                        eventQueue.offer(cb);
                        lock.unlock();
                }
                else {
                        lock.unlock();
                        cb.call();
                }
        }

        public void fire() {
                isFired = true;
                lock.lock();
                lock.unlock();
                while (!eventQueue.isEmpty()) {
                        CallBack cb = eventQueue.poll();
                        cb.call();
                }
        }
}

results matching ""

    No results matching ""