Kaedah Thread.join () di Jawa

1. Gambaran keseluruhan

Dalam tutorial ini, kita akan membincangkan kaedah join () yang berbeza di kelas Thread . Kami akan memperincikan kaedah ini dan beberapa kod contoh.

Seperti kaedah tunggu () dan maklumkan () , gabung () adalah satu lagi mekanisme penyegerakan antara benang.

Anda dapat melihat tutorial ini dengan cepat untuk membaca lebih lanjut mengenai menunggu () dan memberitahu () .

2. Thread.join () Menghubungi

Kaedah bergabung ditakrifkan dalam kelas Thread :

public final batal join () membuang InterruptException

Menunggu benang ini mati.

Apabila kita menggunakan kaedah join () pada utas, utas panggilan masuk ke keadaan menunggu. Ia tetap dalam keadaan menunggu sehingga utas yang dirujuk berakhir.

Kita dapat melihat tingkah laku ini dalam kod berikut:

class SampleThread extends Thread { public int processingCount = 0; SampleThread(int processingCount) { this.processingCount = processingCount; LOGGER.info("Thread Created"); } @Override public void run() { LOGGER.info("Thread " + this.getName() + " started"); while (processingCount > 0) { try { Thread.sleep(1000); } catch (InterruptedException e) { LOGGER.info("Thread " + this.getName() + " interrupted"); } processingCount--; } LOGGER.info("Thread " + this.getName() + " exiting"); } } @Test public void givenStartedThread_whenJoinCalled_waitsTillCompletion() throws InterruptedException { Thread t2 = new SampleThread(1); t2.start(); LOGGER.info("Invoking join"); t2.join(); LOGGER.info("Returned from join"); assertFalse(t2.isAlive()); } 

Kita harus mengharapkan hasil yang serupa dengan yang berikut ketika menjalankan kod:

INFO: Thread Created INFO: Invoking join INFO: Thread Thread-1 started INFO: Thread Thread-1 exiting INFO: Returned from join

Kaedah join () juga boleh kembali sekiranya utas yang dirujuk terganggu . Dalam kes ini, kaedah membuang InterruptException .

Akhirnya, jika utas yang dirujuk sudah ditamatkan atau belum dimulakan, kaedah panggilan untuk bergabung () akan segera kembali .

Thread t1 = new SampleThread(0); t1.join(); //returns immediately

3. Kaedah Thread.join () dengan Timeout

Kaedah join () akan terus menunggu sekiranya urutan yang disekat disekat atau terlalu lama untuk diproses. Ini boleh menjadi masalah kerana utas panggilan akan menjadi tidak responsif. Untuk menangani situasi ini, kami menggunakan versi kaedah join () yang terlalu banyak yang membolehkan kami menentukan jangka masa tamat.

Terdapat dua versi berjangka yang membebankan kaedah join () :

Public final void join (long milis ) melemparkan InterruptException

Menunggu paling banyak milisaat milidetik sehingga benang ini mati. Waktu tamat 0 bermaksud menunggu selama-lamanya. "

"Final public final tidak bergabung ( milis panjang , intnanos ) melemparkan InterruptException

Menunggu paling banyak mil milisaat ditambah nanos nanodetik sehingga benang ini mati. "

Kita dapat menggunakan gabungan berjangka () seperti di bawah:

@Test public void givenStartedThread_whenTimedJoinCalled_waitsUntilTimedout() throws InterruptedException { Thread t3 = new SampleThread(10); t3.start(); t3.join(1000); assertTrue(t3.isAlive()); } 

Dalam kes ini, utas panggilan menunggu kira-kira 1 saat untuk utas t3 selesai. Sekiranya utas t3 tidak selesai dalam jangka masa ini, kaedah bergabung () mengembalikan kawalan ke kaedah panggilan.

Sambungan masa () bergantung pada OS untuk pemasaan. Jadi, kita tidak boleh menganggap bahawa bergabung () akan menunggu selama yang ditentukan.

4. Thread.join () Kaedah dan Penyegerakan

Selain menunggu hingga penamatan, memanggil kaedah join () mempunyai kesan penyegerakan. join () mewujudkan hubungan sebelum-berlaku:

"Semua tindakan dalam utas berlaku-sebelum benang lain berjaya kembali dari gabungan () pada utas itu."

Ini bermaksud bahawa apabila utas t1 memanggil t2.join (), maka semua perubahan yang dilakukan oleh t2 dapat dilihat dalam t1 ketika kembali. Walau bagaimanapun, jika kita tidak memanggil join () atau menggunakan mekanisme penyegerakan lain, kita tidak mempunyai jaminan bahawa perubahan pada thread lain akan dapat dilihat oleh thread semasa walaupun thread lain telah selesai.

Oleh itu, walaupun kaedah join () memanggil ke utas dalam keadaan ditamatkan kembali dengan segera, kita masih perlu memanggilnya dalam beberapa keadaan.

Kita dapat melihat contoh kod penyegerakan yang tidak betul di bawah:

SampleThread t4 = new SampleThread(10); t4.start(); // not guaranteed to stop even if t4 finishes. do { } while (t4.processingCount > 0);

Untuk menyegerakkan kod di atas dengan betul, kita dapat menambahkan t4.join () dalam masa lingkaran atau menggunakan beberapa mekanisme penyegerakan lain.

5. Kesimpulan

kaedah join () cukup berguna untuk penyegerakan antara benang. Dalam artikel ini, kami membincangkan kaedah bergabung () dan tingkah laku mereka. Kami juga mengkaji kod menggunakan kaedah join () .

Seperti biasa, kod sumber penuh boleh didapati di GitHub.