Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android's WorkManager's Simultaneous Job Count/Max

Does WorkManager have a cap to the number of jobs that run at the same time?

Very simple example:

  • Click button, creating 10 one-time jobs
  • Enqueue them all
  • 3 jobs run at a time, instead of all 10 as expected

class MainActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        queue.setOnClickListener {
            val jobs = mutableListOf<OneTimeWorkRequest>()

            for( i in 1..10 ) {
                jobs += OneTimeWorkRequestBuilder<MyWorker>()
                    .setInputData(workDataOf("key" to i))
                    .build()
            }

            WorkManager.getInstance().enqueue(jobs)
        }
    }
}

class MyWorker: Worker() {
    override fun doWork(): Result {
        val jobId = inputData.getInt("key", -1)

        Log.d("worker", "starting job: $jobId")

        Completable.timer(10, SECONDS).blockingGet()

        Log.d("worker", "job finished: $jobId")

        return SUCCESS
    }
}

And the output:

08-30 14:03:10.392  9825  9855 D worker  : starting job: 2
08-30 14:03:10.396  9825  9856 D worker  : starting job: 3
08-30 14:03:10.400  9825  9854 D worker  : starting job: 1
08-30 14:03:20.421  9825  9855 D worker  : job finished: 2
08-30 14:03:20.421  9825  9856 D worker  : job finished: 3
08-30 14:03:20.421  9825  9854 D worker  : job finished: 1
08-30 14:03:20.442  9825  9856 D worker  : starting job: 4
08-30 14:03:20.448  9825  9854 D worker  : starting job: 5
08-30 14:03:20.450  9825  9855 D worker  : starting job: 6
08-30 14:03:30.444  9825  9856 D worker  : job finished: 4
08-30 14:03:30.449  9825  9854 D worker  : job finished: 5
08-30 14:03:30.451  9825  9855 D worker  : job finished: 6
08-30 14:03:30.474  9825  9856 D worker  : starting job: 7
08-30 14:03:30.477  9825  9855 D worker  : starting job: 8
08-30 14:03:30.480  9825  9854 D worker  : starting job: 9
08-30 14:03:40.476  9825  9856 D worker  : job finished: 7
08-30 14:03:40.478  9825  9855 D worker  : job finished: 8
08-30 14:03:40.481  9825  9854 D worker  : job finished: 9
08-30 14:03:40.497  9825  9856 D worker  : starting job: 10
08-30 14:03:50.500  9825  9856 D worker  : job finished: 10
like image 948
Jamie Dulaney Avatar asked Aug 30 '18 14:08

Jamie Dulaney


1 Answers

The number of jobs that can run at the same time are actually determined by a thread pool that you configure. The default Executor is defined here.

Typically when you are using the Worker base class, you are associating an instance of the Worker to a thread on this Executor. If you want greater control on which thread your Worker is associated with, you might want to take a look at CoroutineWorker or ListenableWorker.

The number of threads in the default Executor are determined by the number of cores on the device. If you want all 10 jobs to run at the same time you have to do the following:

  • Disable the default WorkManager initializer (by disabling manifest merging for the content provider).

  • Initialize WorkManager on Application.onCreate() or your own ContentProvider. You need to do this here because the OS can ask previously scheduled Workers to run. For more information look at this.

val configuration = Configuration.Builder()
    // Defines a thread pool with 10 threads. 
    // Ideally you would choose a number that is dynamic based on the number 
    // of cores on the device.
    .setExecutor(Executors.newFixedThreadPool(10))
    .build()

WorkManager.initialize(context, configuration)

In the above example I am creating a fixed size thread pool with 10 threads (which in turn can handle 10 Workers). Now when you enqueue your Workers you will see all of them execute at the same time.

like image 110
Rahul Avatar answered Sep 22 '22 19:09

Rahul