异步模式备忘
- java web 中使用异步调用
-
如果在servlet中接收到一次请求,这时候启动一个新的线程进行耗时操作或者异步得到回调结果时
- servlet中需要阻塞,等待新新线程中的返回结果 否则就会运行完毕直接返回给客户端了这时候还没有结果
while (! completed){
try {
lock.wait();
//注意必须是拥有synchronized锁的对象才能调用wait否则会IllegalMonitorStateException异常
} catch (Throwable t) {
}
}
在新的线程中完成操作时,设置 ‘completed=true’ 同时唤醒servlet中线程 notifyAll()
一般我们会封装成一个对象来调用:
public class Feature {
private Object result = null;
private boolean completed = true;
private Object lock = new Object();
public void doing(){
//业务逻辑,耗时操作。。。
try {
this.complete = false;
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized(this.lock){
this.result = new Object();
this.completed = true;
try {
this.lock.notify();
} catch (Throwable t) {
this.logger.error(t.getMessage(),t);
return t.getMessage();
}
}
}
public Object getResult(){
synchronized(this.lock){
while (!this.completed){
try {
this.lock.wait();
} catch (Throwable t) {
}
}
}
this.completed = true;
return this.result;
}
}
在servlet中调用:
public Object response() {
final Feature feature = new Feature();
new Thread(new Runnable() {
public void run() {
feature.doing();
}
}).start();
Object result = feature.getResult();
return result;
}
上面代码中,feature.doing 同一个feature对象的doing方法,在新的线程中调用
feature.getResult() 是在当前线程中调用,wait() 会使当前线程挂起,不会拼命进行while(true) 的空循环,等待doing完成时,新线程中唤醒当前被挂起的线程 completed标识,可以判断当前对象feature是否完成,即使有其他新的线程(做其他任务)唤醒时,当前逻辑也不会有问题。而且,每个servlet 接收到的请求都可以 new Feature() 不需要考虑同步问题(因为我看到有的博客上,在Feature内部的方法中加入了synchronized)。
- android 中的异步handler使用
:UI界面的异步不一样,不需要web中及时的返回,或者说随时可以根据异步返回结果更改界面,
所以不需要while(true) {wait();} 进行阻塞挂起线程,所以在设计界面的异步调用时,应该使用匿名内部类来解决变量传值等问题,匿名内部类的好处是,其实现方法完全写在内部,可以直接调用修改外部类的UI,用反射的形式,也可以把方法写在UI类中,类似xUtils的用法。