2

I got the trouble with using synchronized the object in background thread. I've specified the problem in sample nutshell:

  1. I write the simple class like that:

    public class UIThreadClass {
    
       MyObject object;
    
       UIThreadClass() {
          object = new MyObject();
    
          object.doActionOne();
          object.doActionTwo();
      }
    }
    
  2. Now my task is improve the code by put two method to non-UI thread. I am using AsyncTask

    For doActionOne()

    private static class DoActionOneTask extends AsyncTask<Void, Void, Void> {
    
        private WeakReference<MyObject> wObject;
    
        DoActionOneTask(MyObject object) {
            wObject = new WeakReference<>(object);
        }
    
        @Override
        protected Void doInBackground(Void... voids) {
           if(wObject.get() != null) {
              MyObject myObject = wObject.get();
              myObject.doActionOne();
           }
    
           return null;
        }
    }
    

    For doActionTwo()

    private static class DoActionTwoTask extends AsyncTask<Void, Void, Void> {
    
        private WeakReference<MyObject> wObject;
    
        DoActionOneTask(MyObject object) {
            wObject = new WeakReference<>(object);
        }
    
        @Override
        protected Void doInBackground(Void... voids) {
           if(wObject.get() != null) {
              MyObject myObject = wObject.get();
              myObject.doActionTwo();
           }
    
           return null;
        }
    }
    

    Now call them in UI thread

    public class UIThreadClass {
    
       MyObject object;
    
       UIThreadClass() {
          object = new MyObject();
    
          new DoActionOneTask(object).execute();
          new DoActionTwoTask(object).execute();
      }
    }
    

The question is:

When using AsyncTask - how to synchronized the object to make sure that the doActionTwo() alway call after doActionOne() method ?.

I have tried using synchronized (myObject) {myObject.doActionOne();} in doInBackground() but the system is warning me that myObject just local variable and it is difficult to guarantee correctness.

Can anyone help me this situation ? Thanks a lot!

  • AsyncTask as the name suggest it will perform the task asynchronously, You can create a separate thread and perform operations and synchronise them – Akshay Katariya Apr 19 '18 at 05:05
  • instead of synchronized use ThreadPoolExecutor that will run simultaneously. for more have look [this](https://stackoverflow.com/a/47466464/5110595) – Hemant Parmar Apr 19 '18 at 05:07
  • 1
    you can start your 2nd Asynctask from the first one's onPostExecute method or use ThreadPoolExecutor – himel Apr 19 '18 at 05:08
  • BTW the way you use WeakReference is not safe, you should store the `wObject.get()`in a variable and perform your if-statement. Calling `wObject.get()` again can potentially give a null reference at some point. – Enzokie Apr 19 '18 at 05:56
  • @AkshayKatariya: But what I want is "how to synchronized". The problem is solved, thanks – Truong Giang Dam Apr 19 '18 at 06:39
  • @HemantParmar: Yeah, I know about ThreadPoolExecutor, but my task is using both of them and compare between. The problem is solved, thanks. – Truong Giang Dam Apr 19 '18 at 06:40
  • @himel: thanks for you suggestion but not using onPostExecute here because of not using callback requirement. The problem is solved, thanks – Truong Giang Dam Apr 19 '18 at 06:41
  • @Enzokie: Can you explain why calling wObject.get() again can potentially give a null reference, pls ? – Truong Giang Dam Apr 19 '18 at 06:46

1 Answers1

2

You don't need to do anything. They will execute serially as per the Android docs

Order of execution
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
Raj Suvariya
  • 1,592
  • 3
  • 14
  • 36