目标
- 实现对一批id进行多线程的并行处理, 处理完成之后需要得到处理结果
- 如: [1,2,5,8,11,22,44], 这一批id被三个线程执行更新操作, 执行完成之后需要得到执行的结果
实现
定义观察者接口
- 此方法是当任务执行完成时回调的方法
public interface LifeCycleListener {
void onEvent(ObserverableRunnable.RunnableEvent event);
}
定义被观察者
- 创建当前对象时需要拿到谁监听我
- 在状态变化时调用监听者的通知方法
- 监听方只需要保证onEvent方法里面的代码在多线程情况下没有问题
注意:此处被观察实际上就是任务对象,但是具体任务该如何执行在这里没有实现,此处直接定义为抽象类,是因为大多数的业务场景不一样样所以具体的业务实现交给调用者实现,此处只实现回调
public abstract class ObserverableRunnable implements Runnable{
/**
* 监听这
*/
final protected LifeCycleListener listener;
public ObserverableRunnable(LifeCycleListener listener) {
this.listener = listener;
}
public void notifyChange(final RunnableEvent event) {
listener.onEvent(event);
}
public enum RunnableState {
RUNNING, ERROR, DONE;
}
/**
* 内部类尽量都是静态的,不然作为成员对象每次创建对象都会复制
*/
public static class RunnableEvent {
private final RunnableState state;
private final Thread thread;
private final Throwable cause;
public RunnableEvent(RunnableState state, Thread thread, Throwable cause) {
this.state = state;
this.thread = thread;
this.cause = cause;
}
public RunnableState getState() {
return state;
}
public Thread getThread() {
return thread;
}
public Throwable getCause() {
return cause;
}
}
}
观察者实现
- 此处模拟一批id被处理最后打印处理结果
/**
* 模拟当前类使用多线程需要去处理一批id,并拿到结果
* 1. 创建处理方法并通过ObserverableRunnable去执行任务
* 2. 当ObserverableRunnable吧任务执行完成后提醒当前类做完了
* 3. 拿到返回值处理
*/
public class ThreadLifeCycleObserver implements LifeCycleListener {
private Object LOCK = new Object();
private void concurrentQuery(List<Integer> ids) {
if (ids.size() == 0 && ids.isEmpty())
return;
ids.stream().forEach((id)->{
new Thread(new ObserverableRunnable(this) {
@Override
public void run() {
try {
notifyChange(new RunnableEvent(RunnableState.RUNNING, Thread.currentThread(), null));
System.out.printf("query for id = %s\n", id);
Thread.sleep(1000);
notifyChange(new RunnableEvent(RunnableState.DONE, Thread.currentThread(), null));
} catch (InterruptedException e) {
notifyChange(new RunnableEvent(RunnableState.ERROR, Thread.currentThread(), e));
}
}
}).start();
});
}
/**
* 这个方法可能是多个线程在回调所以需要使用同步锁
* @param event
*/
@Override
public void onEvent(ObserverableRunnable.RunnableEvent event) {
synchronized (LOCK) {
System.out.println(event.getThread().getName() + " == " + event.getState());
}
}
public static void main(String[] args) {
ThreadLifeCycleObserver threadLifeCycleObserver = new ThreadLifeCycleObserver();
threadLifeCycleObserver.concurrentQuery(Arrays.asList(1, 2, 3));
}
}