Android's WorkManager's Simultaneous Job Count/Max
Asked Answered
P

1

5

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
Prudery answered 30/8, 2018 at 14:33 Comment(2)
did you got any updates on this?Hauger
No, I have not received any updates on thisPrudery
F
9

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.

Frontwards answered 23/1, 2019 at 2:17 Comment(2)
A limiting factor to consider for the number of workers is if you have dependencies between workers. You will get an IllegalStateException "Data cannot occupy more than 10240 bytes when serialized" if you have a WorkerB that depends on 1000 WorkerA's that pass some minimal amount of data.Chivy
While this sounds logical, in my case I set this to a single-threaded executor. But it still starts doWork of multiple workers simultaneously. The configuration is correct, I made sure it gets called. Just super confused right now...Antependium

© 2022 - 2024 — McMap. All rights reserved.