Java memiliki thread khusus, yaitu thread daemon, yang mempunyai prioritas sangat rendah dan hanya akan dieksekusi ketika thread lain dalam program yang sama tidak dijalankan.
Karena thread daemon memiliki karakteristik ini, thread tersebut umumnya digunakan untuk menyediakan layanan bagi thread biasa (juga disebut thread pengguna) dalam program. Mereka umumnya memiliki loop tak terbatas, atau digunakan untuk menunggu layanan permintaan, atau untuk melakukan tugas, dll. Mereka tidak dapat melakukan pekerjaan penting apa pun karena kami tidak yakin kapan mereka akan diberi waktu CPU, dan mereka akan secara otomatis berhenti ketika tidak ada thread lain yang dijalankan. Aplikasi khas dari jenis thread ini adalah pengumpulan sampah Java.
Pada contoh di bagian ini, kita akan membuat dua thread, satu adalah thread normal, yang menulis event ke antrian; yang lainnya adalah thread daemon, yang menghapus event dalam antrian dan menghapus event yang ada selama lebih dari 10 detik.
mengetahuinya
Ikuti langkah-langkah di bawah ini untuk mengimplementasikan program contoh.
1. Buat kelas Event, yang hanya digunakan untuk menyimpan informasi event yang diperlukan untuk eksekusi program. Deklarasikan dua properti, satu adalah properti tanggal dari tipe java.util.Date, dan yang lainnya adalah properti event dari tipe String; Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Acara kelas publik {
tanggal Tanggal pribadi;
acara String pribadi;
Tanggal publik getDate() {
tanggal kembali;
}
public void setDate(Tanggal tanggal) {
this.tanggal = tanggal;
}
String publik getEvent() {
acara pengembalian;
}
public void setEvent(String acara) {
this.acara = acara;
}
}
2. Buat kelas bernama WriterTask dan implementasikan antarmuka Runnable. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
kelas publik WriterTask mengimplementasikan Runnable {
3. Mendeklarasikan atribut antrian yang digunakan untuk menyimpan peristiwa, mengimplementasikan konstruktor kelas, dan menggunakan parameternya untuk menginisialisasi atribut antrian. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Deque pribadi<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
4. Implementasikan metode run() pada tugas ini, yang berisi loop yang melintasi 100 kali. Pada setiap traversal, objek Event baru dibuat, kemudian disimpan ke antrian, dan tidur selama 1 detik. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
@Mengesampingkan
menjalankan kekosongan publik() {
untuk (int saya = 0; saya < 100; saya++) {
Acara acara = Acara baru();
acara.setDate(Tanggal baru());
event.setEvent(String.format("Thread %s telah menghasilkan sebuah acara",
Thread.currentThread().getId()));
deque.addFirst(acara);
mencoba {
TimeUnit.SECONDS.sleep(1);
} tangkapan (InterruptedException e) {
e.printStackTrace();
}
}
}
5. Buat kelas bernama CleanerTask dan warisi kelas Thread. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
kelas publik CleanerTask memperluas Thread {
6. Mendeklarasikan atribut antrian yang digunakan untuk menyimpan peristiwa, mengimplementasikan konstruktor kelas, dan menggunakan parameternya untuk menginisialisasi atribut antrian. Dalam metode konstruksi, atur thread sebagai thread daemon dengan memanggil metode setDaemon(). Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Deque pribadi<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(benar);
}
7. Implementasikan metode run(). Ada loop tak terbatas di badan metode untuk mendapatkan waktu saat ini dan kemudian memanggil metode clearn(). Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
@Mengesampingkan
menjalankan kekosongan publik() {
sementara (benar) {
Tanggal tanggal = Tanggal baru();
bersih (tanggal);
}
}
8. Terapkan metode clean(). Dalam metode ini, dapatkan waktu terakhir, lalu periksa perbedaan waktu antara waktu dan waktu saat ini. Jika dibuat 10 detik yang lalu, hapus acara saat ini, lalu periksa acara berikutnya peristiwa. Jika suatu event dihapus maka informasi event yang terhapus tersebut akan tercetak, dan panjang antrian terakhir juga akan tercetak, sehingga dapat diamati kemajuan eksekusi program. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
private void clean(Tanggal tanggal) {
perbedaan jauh;
hapus boolean;
if (deque.ukuran() == 0) {
kembali;
}
hapus = salah;
Mengerjakan {
Acara e = deque.getLast();
perbedaan = tanggal.getTime() - e.getDate().getTime();
jika (selisih > 10.000) {
System.out.printf("Pembersih: %s/n", e.getDate());
deque.removeLast();
hapus = benar;
}
} while (selisih > 10.000);
jika (hapus) {
System.out.printf("Pembersih: Ukuran antrian: %d/n", deque.size());
}
}
9. Buat kelas utama program, kelas Utama, lalu implementasikan metode main(). Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
kelas publik Utama {
public static void main(String[] args) {
10. Gunakan kelas Deque untuk membuat antrian untuk menyimpan acara. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Deque<Event> deque = ArrayDeque baru<>();
11. Buat dan mulai tiga thread WriterTask dan satu thread CleanerTask. Kodenya adalah sebagai berikut:
Copy kode kodenya sebagai berikut:
Deque<Event> deque = ArrayDeque baru<>();
WriterTask penulis = WriterTask baru(deque);
untuk (int saya = 0; saya < 3; saya++) {
Thread thread = Thread baru (penulis);
thread.mulai();
}
Pembersih CleanerTask = CleanerTask baru(deque);
pembersih.mulai();
12. Jalankan program dan lihat hasil eksekusinya.
tahu kenapa
Menganalisis hasil eksekusi program, kita dapat melihat bahwa antrian mula-mula bertambah menjadi 30, kemudian berubah antara 27 dan 30 hingga eksekusi program berakhir.
Program pertama-tama mulai mengeksekusi dari tiga thread WriterTask. Setiap thread terlebih dahulu menambahkan acara ke antrean dan kemudian tidur selama 1 detik. Setelah 10 detik pertama berlalu, akan ada tiga puluh peristiwa dalam antrian. Selama 10 detik ini, ketika ketiga thread WriterTask tertidur, thread CleanerTask juga akan berjalan, namun tidak ada kejadian yang akan dihapus karena waktu pembuatan semua kejadian tidak melebihi 10 detik. Setelah 10 detik pertama, tiga WriterTasks menambahkan tiga peristiwa ke antrian setiap detik; demikian pula, CleanerTask menghapus tiga peristiwa setiap detik; Jadi, jumlah kejadian berkisar antara 27 dan 30.
Ketika semua thread WriterTask tertidur, kita bebas memproses waktu, sehingga thread daemon dapat berjalan selama waktu tersebut. Jika Anda mengatur waktu tidur thread WriterTask menjadi lebih singkat, thread CleanerTask akan mendapatkan waktu berjalan CPU yang lebih sedikit. Jika hal ini terjadi, panjang antrian akan terus bertambah karena thread CleanerTask tidak pernah mendapatkan waktu berjalan yang cukup untuk menghapus cukup banyak peristiwa.
tidak pernah berakhir
Thread hanya dapat disetel sebagai thread daemon dengan memanggil metode setDaemon() sebelum memanggil metode start(). Setelah thread mulai berjalan, status daemon tidak dapat diubah.
Anda juga dapat menggunakan isDaemon() untuk memeriksa apakah suatu thread merupakan thread daemon. Jika itu adalah thread daemon, ia mengembalikan nilai true; jika itu adalah thread biasa, ia mengembalikan false.
Gunakan doktrin
Artikel ini diterjemahkan dari "Buku Masak Konkurensi Java 7" (D Gua Ge mencurinya sebagai "Koleksi Contoh Konkurensi Java7") dan hanya digunakan sebagai bahan pembelajaran. Ini tidak boleh digunakan untuk tujuan komersial apa pun tanpa izin.
Keberhasilan kecil
Versi lengkap dari semua kode contoh yang digunakan di bagian ini.
Kode lengkap kelas Acara
Copy kode kodenya sebagai berikut:
paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
/**
*Kelas informasi acara
* Tanggal: 19-09-2013
* Waktu: 22:56
*/
Acara kelas publik {
tanggal Tanggal pribadi;
acara String pribadi;
Tanggal publik getDate() {
tanggal kembali;
}
public void setDate(Tanggal tanggal) {
this.tanggal = tanggal;
}
String publik getEvent() {
acara pengembalian;
}
public void setEvent(String acara) {
this.acara = acara;
}
}
Kode lengkap kelas WriterTask
Copy kode kodenya sebagai berikut:
paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
import java.util.bersamaan.TimeUnit;
/**
* Hasilkan acara setiap detik.
* Tanggal: 19-09-2013
* Waktu: 22:59
*/
kelas publik WriterTask mengimplementasikan Runnable {
Deque pribadi<Event> deque;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Mengesampingkan
menjalankan kekosongan publik() {
untuk (int saya = 0; saya < 100; saya++) {
Acara acara = Acara baru();
acara.setDate(Tanggal baru());
event.setEvent(String.format("Thread %s telah menghasilkan sebuah acara",
Thread.currentThread().getId()));
deque.addFirst(acara);
mencoba {
TimeUnit.SECONDS.sleep(1);
} tangkapan (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Kode lengkap kelas CleanerTask
Copy kode kodenya sebagai berikut:
paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
import java.util.Date;
import java.util.Deque;
/**
* Pembersihan acara
* Tanggal: 19-09-2013
* Waktu: 23:33
*/
kelas publik CleanerTask memperluas Thread {
Deque pribadi<Event> deque;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(benar);
}
@Mengesampingkan
menjalankan kekosongan publik() {
sementara (benar) {
Tanggal tanggal = Tanggal baru();
bersih (tanggal);
}
}
/**
* Hapus acara.
*
* @param tanggal
*/
private void clean(Tanggal tanggal) {
perbedaan jauh;
hapus boolean;
if (deque.ukuran() == 0) {
kembali;
}
hapus = salah;
Mengerjakan {
Acara e = deque.getLast();
perbedaan = tanggal.getTime() - e.getDate().getTime();
jika (selisih > 10.000) {
System.out.printf("Pembersih: %s/n", e.getDate());
deque.removeLast();
hapus = benar;
}
} while (selisih > 10.000);
jika (hapus) {
System.out.printf("Pembersih: Ukuran antrian: %d/n", deque.size());
}
}
}
Kode lengkap kelas Utama
Copy kode kodenya sebagai berikut:
paket com.diguage.books.concurrencycookbook.chapter1.recipe7;
impor java.util.ArrayDeque;
import java.util.Deque;
/**
* Tanggal: 19-09-2013
* Waktu: 23:54
*/
kelas publik Utama {
public static void main(String[] args) {
Deque<Event> deque = ArrayDeque baru<>();
WriterTask penulis = WriterTask baru(deque);
untuk (int saya = 0; saya < 3; saya++) {
Thread thread = Thread baru (penulis);
thread.mulai();
}
Pembersih CleanerTask = CleanerTask baru(deque);
pembersih.mulai();
}
}