我有一个方法goToNextScreen()
,它检查3个不同的异步过程,所以当所有过程完成后,验证将改变活动(是一种Splash活动)
我的示例代码从3个不同的结果回调访问活动的方法goToNextScreen(),更新每个进程的标志值并验证其中的其他标志。
到目前为止,这种方法有效,但我有下一个问题:
这种方法有效吗?是否存在某种死锁的风险?所有线程/回调都不会同时碰撞访问该方法导致错误的验证?
class LoadingActivity extends Activity{
public boolean isFetchDone, isAnimationDone, isServiceDone, watchDog;
Presenter presenter;
protected void onCreate(@Nullable Bundle savedInstanceState) {
presenter(this);
runAnimation();
presenter.runGetXService();
runFetchFromDB();
}
//do some generic isAnimationDone
private void runAnimation(){
//animator set and animation assumed to be correct...
//...
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// do anything before animation start
}
@Override
public void onAnimationEnd(Animator animation) {
isAnimationDone = true;
goToNextScreen();
}
@Override
public void onAnimationCancel(Animator animation) {
// do something when animation is cancelled (by user/ developer)
}
@Override
public void onAnimationRepeat(Animator animation) {
// do something when animation is repeating
}
});
}
//Some example function to fetch data from x DB
private void runFetchFromDB() {
final Realm realm = RealmProvider.getInstance();
final ThingDB db = new ThingDBImpl(realm);
realm.beginTransaction();
db.getData(10L)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<XData>() {
@Override
public void onCompleted() {
isFetchDone = true;
goToNextScreen();
}
@Override
public void onError(Throwable e) {
//we dont care about the result
isFetchDone = true;
goToNextScreen();
}
@Override
public void onNext(XData dataSaved) {
//Should i update isFetchDone here?
});
realm.cancelTransaction();
}
private synchronized void goToNextScreen(){
if(!watchDog) return;
if(isFetchDone && isAnimationDone && isServiceDone){
changeActivityFaded(this, SomeOtherActivity);
finish();
watchDog = true;
}
}
}
class Presenter {
Activity activity;
Presenter(Activity activity){
this.activity = activity;
}
public void runGetXService(){
new Presenter.GetServiceAsyncTask().execute();
}
private class GetServiceAsyncTask extends AsyncTask<Void, Void, Response> {
@Override
protected void onPreExecute() {
super.onPreExecute();
//do preparation for service response, etc, asumme all correct
}
@Override
protected XResponse doInBackground(Void... voids) {
try {
return //Assume correct behaviour...
} catch (NetworkConnectionException e) {
return null;
}
}
@Override
protected void onPostExecute(XResponse xResponse) {
super.onPostExecute(xResponse);
((LoadingActivity)activity).isServiceDone = true;
((LoadingActivity)activity).goToNextScreen();
}
}
}
修改
我已将方法goToNextScreen
更改为synchronized
,因此它不应允许同时访问其他线程。如果执行是正确的,仍然有疑问。
答案 0 :(得分:1)
是的,使方法同步意味着它不能同时执行多次。如果第二个线程在它仍在执行时调用它,则第二个线程将阻塞,直到释放同步锁。
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
答案 1 :(得分:0)
到目前为止,这种方法通过将synchronized添加到访问它的线程上共享的活动实例的方法goToNextScreen成员到目前为止已经工作。 (查看解决方案的问题代码)。虽然我需要添加一个看门狗,以防一些线程传递执行它应该执行一次的代码。