还有老题Event/Fire多线程。详细题目解释可以参考:https:
大意就是一个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();
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();
}
}
}