ThreadPoolTaskExecutor corePoolSize vs maxPoolSize

1. Gambaran keseluruhan

Spring ThreadPoolTaskExecutor adalah JavaBean yang memberikan abstraksi di sekitar java.util.concurrent.ThreadPoolExecutor dan memperlihatkannya sebagai Spring.springframework.core.task.TaskExecutor . Selanjutnya, ia sangat dapat dikonfigurasi melalui sifat corePoolSize, maxPoolSize, queueCapacity, allowCoreThreadTimeOut dan keepAliveSeconds. Dalam tutorial ini, kita akan melihat corePoolSize dan maxPoolSize hartanah.

2. corePoolSize vs maxPoolSize

Pengguna yang baru menggunakan abstraksi ini mungkin mudah bingung mengenai perbezaan dua sifat konfigurasi. Oleh itu, mari kita lihat masing-masing secara bebas.

2.1. corePoolSize

The corePoolSize adalah bilangan minimum pekerja untuk menjaga hidup tanpa masa keluar. Ia adalah harta ThreadPoolTaskExecutor yang boleh dikonfigurasi . Walau bagaimanapun, abstraksi ThreadPoolTaskExecutor menetapkan nilai ini ke java.util.concurrent.ThreadPoolExecutor yang mendasari . Untuk menjelaskan, semua utas mungkin akan habis - dengan berkesan menetapkan nilai corePoolSize menjadi sifar jika kita telah menetapkan allowCoreThreadTimeOut ke true .

2.2. maxPoolSize

Sebaliknya, maxPoolSize menentukan bilangan utas maksimum yang boleh dibuat . Begitu juga dengan maxPoolSize harta ThreadPoolTaskExecutor juga perwakilan nilai kepada asas java.util.concurrent.ThreadPoolExecutor . Untuk memperjelas, maxPoolSize bergantung pada queueCapacity dalam ThreadPoolTaskExecutor hanya akan membuat utas baru jika bilangan item dalam barisannya melebihi queueCapacity .

3. Jadi Apa Perbezaannya?

Perbezaan antara corePoolSize dan maxPoolSize mungkin kelihatan jelas. Walau bagaimanapun, terdapat beberapa kehalusan mengenai tingkah laku mereka.

Apabila kami menyerahkan tugas baru ke ThreadPoolTaskExecutor, ia membuat utas baru jika lebih sedikit daripada utas corePoolSize berjalan, walaupun terdapat utas terbiar di kolam, atau jika lebih sedikit daripada utas maxPoolSize sedang berjalan dan barisan yang ditentukan oleh queueCapacity penuh.

Seterusnya, mari kita lihat beberapa kod untuk melihat contoh kapan setiap harta tanah bertindak.

4. Contohnya

Pertama, katakan kita mempunyai kaedah yang menjalankan utas baru, dari ThreadPoolTaskExecutor , bernama startThreads :

public void startThreads(ThreadPoolTaskExecutor taskExecutor, CountDownLatch countDownLatch, int numThreads) { for (int i = 0; i  { try { Thread.sleep(100L * ThreadLocalRandom.current().nextLong(1, 10)); countDownLatch.countDown(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } }

Mari kita uji konfigurasi lalai ThreadPoolTaskExecutor , yang menentukan corePoolSize satu utas, maxPoolSize tanpa had , dan queueCapacity tanpa had . Hasilnya, kami menjangkakan tidak kira berapa banyak tugas yang kami mulakan, kami hanya akan menjalankan satu utas:

@Test public void whenUsingDefaults_thenSingleThread() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(1, taskExecutor.getPoolSize()); } }

Sekarang, mari kita ubah corePoolSize menjadi maksimum lima utas dan pastikan ia berperilaku seperti yang diiklankan. Hasilnya, kami menjangkakan lima utas akan dimulakan tidak kira jumlah tugas yang diserahkan kepada ThreadPoolTaskExecutor :

@Test public void whenCorePoolSizeFive_thenFiveThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(5, taskExecutor.getPoolSize()); } }

Begitu juga, kita dapat meningkatkan maxPoolSize hingga sepuluh sambil meninggalkan corePoolSize pada lima. Hasilnya, kami menjangka hanya akan memulakan lima utas. Untuk menjelaskan, hanya lima utas yang bermula kerana queueCapacity masih tidak terhad:

@Test public void whenCorePoolSizeFiveAndMaxPoolSizeTen_thenFiveThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(10); this.startThreads(taskExecutor, countDownLatch, 10); while (countDownLatch.getCount() > 0) { Assert.assertEquals(5, taskExecutor.getPoolSize()); } }

Selanjutnya, kita sekarang akan mengulangi ujian sebelumnya tetapi meningkatkan queueCapacity menjadi sepuluh dan memulakan dua puluh utas . Oleh itu, kami kini menjangkakan sepuluh utas keseluruhan:

@Test public void whenCorePoolSizeFiveAndMaxPoolSizeTenAndQueueCapacityTen_thenTenThreads() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(10); taskExecutor.afterPropertiesSet(); CountDownLatch countDownLatch = new CountDownLatch(20); this.startThreads(taskExecutor, countDownLatch, 20); while (countDownLatch.getCount() > 0) { Assert.assertEquals(10, taskExecutor.getPoolSize()); } }

Begitu juga, jika kita telah menetapkan queueCapactity menjadi sifar dan hanya memulakan sepuluh tugas, kita juga mempunyai sepuluh utas dalam ThreadPoolTaskExecutor kami .

5. Kesimpulan

ThreadPoolTaskExecutor adalah abstraksi yang kuat di sekitar java.util.concurrent.ThreadPoolExecutor , menyediakan pilihan untuk mengkonfigurasi corePoolSize , maxPoolSize , dan queueCapacity . Dalam tutorial ini, kita melihat kepada corePoolSize dan maxPoolSize hartanah, serta bagaimana maxPoolSize berfungsi seiring dengan queueCapacity , membolehkan kita dengan mudah membuat kolam thread bagi apa-apa kes penggunaan.

Seperti biasa, anda boleh mendapatkan kod yang terdapat di Github.