Question

I have a AsyncTask called UploadManager in my Android Application, that checks for processed items, and uploads them to the server.
For this purpose I'm using the ScheduledExecutorService.scheduleAtFixedRate to check for items after every 1 minute, and upload them to server.
However, at times, there are multiple pools of thread created (this happens like 10% of the times), due to which at times the same request is send twice to the server, though this concurrency is handled at both the server & client level, but I still don't want this to happen on the client side.
Below is how the code looks like.
In the MainActivity (start-activity), I initiate the UploadManager as:

public class MainActivity extends BaseActivity {

   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       .
       .
       .
       new UploadManager().execute(this);
   }
}

UploadManager works as follows:

public class UploadManager extends AsyncTask<Context, Integer, Integer> {

    private ScheduledExecutorService scheduledExecutorService;
    private static final int NUM_OF_THREADS = 5;
    private static final int DELAY_IN_SECONDS = 60;
    private Context context;
    private final Logger logger = new Logger(getClass().getSimpleName());

    protected Integer doInBackground(Context... context) {
        this.context = context[0];
        scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS);
        scheduledExecutorService.scheduleAtFixedRate(postInformation, 5, DELAY_IN_SECONDS, TimeUnit.SECONDS);
       return 0;
    }

    private Runnable postInformation = new Runnable() {
        @Override
        public void run() {
            if (NetworkManager.isInternetAvailable(context)) {
                uploadAcknowledgement();
            }
        }
    };

    private void uploadAcknowledgement() {
        List<Acknowledgement> ackList = null;
        try {
            logger.info("RUNNING TASK TO POST ACKNOWLEDGEMENT");
            .
            .
        }
    }
}

When I checked the logs, it says:

35119 [pool-2-thread-1] INFO  Upload Manager - [1363841355530] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT  
35122 [pool-3-thread-1] INFO  Upload Manager - [1363841355532] : 21/03/2013 10:19:15 : RUNNING TASK TO POST ACKNOWLEDGEMENT

Which clearly indicates that there are multiple pools of thread now, due to which, uploadAcknowledgement() method is called multiple-times.

The MainActivity is declared in AndroidManifest.xml as:

<application android:label="@string/app_name" android:icon="@drawable/icon">
    <activity android:name="MainActivity"
              android:label="@string/app_name"
              android:theme="@android:style/Theme.NoTitleBar">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
        </intent-filter>
    </activity>
    .
    .

Was it helpful?

Solution

I eventually figured out the reasons, if the ScheduledExecutor's service runs overlap, then it spawns new worker threads (eg. in this case postInformation() creates a new worker thread) and eventually, a new pool.
However, multiple workers can be avoided by using newSingleThreadScheduledExecutor instead of newScheduledThreadPool(int corePoolSize)'.
So, instead of initialising `scheduledExecutorService' as:

scheduledExecutorService = Executors.newScheduledThreadPool(NUM_OF_THREADS);  

It should have been be initialised as:

scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();  

This way it will be ensured that there are no multiple worker threads running.

OTHER TIPS

You have a list of N number of files and started X number of threads to upload it without specifying which thread to pick which file. One approach to solve this to add the files to be uploaded into a Blocking Queue and let the threads pick the files to be uploaded from the Queue. This way no file will be picked twice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top