Ketika suatu objek mengubah keadaan jangkauannya, referensi ke objek dapat ditempatkan dalam antrian referensi. Antrian ini digunakan oleh pengumpul sampah untuk berkomunikasi dengan kode kami tentang perubahan aksesibilitas objek. Antrian ini adalah cara terbaik untuk mendeteksi perubahan aksesibilitas, meskipun kami juga dapat mendeteksi perubahan aksesibilitas objek dengan memeriksa apakah nilai pengembalian metode GET adalah nol.
Objek referensi dapat dikaitkan dengan antrian spesifik saat dibangun. Setiap subkelas referensi menyediakan konstruktor dari bentuk berikut:
Referensi Kekuatan Publis (Referensi T, ReferenceQueueQ): Metode ini membuat objek referensi baru dengan objek referensi yang diberikan dan mendaftarkan objek referensi ke antrian yang diberikan. Referensi yang lemah dan referensi lunak dimasukkan ke dalam antrian setelah pengumpul sampah menentukan bahwa objek referensi mereka memasuki keadaan jangkauan spesifik yang mereka wakili, dan kedua referensi dibersihkan sebelum antrian penyisipan. Referensi virtual juga akan dimasukkan ke dalam antrian setelah pengumpul sampah menentukan bahwa objek rujukannya telah memasuki keadaan virtual yang dapat dijangkau, tetapi mereka tidak akan dibersihkan. Setelah objek referensi dimasukkan ke dalam antrian oleh pengumpul sampah, nilai pengembalian metode GET pasti akan menjadi nol, sehingga objek tidak akan pernah bisa dibangkitkan.
Mendaftarkan objek referensi ke antrian referensi tidak membuat referensi antara antrian dan objek referensi. Jika objek referensi kami sendiri menjadi tidak terjangkau, itu tidak dapat dimasukkan ke dalam antrian. Oleh karena itu, aplikasi kami perlu mempertahankan referensi yang kuat untuk semua objek yang direferensikan.
Kelas ReferenceQueue menyediakan tiga metode untuk menghapus referensi dalam antrian:
Metode jajak pendapat memungkinkan utas untuk menanyakan apakah referensi ada dalam antrian dan melakukan tindakan tertentu ketika referensi ada dalam antrian. Metode Hapus dapat menangani situasi yang lebih kompleks (kurang umum), di mana utas khusus bertanggung jawab untuk menghapus referensi dari antrian dan melakukan tindakan yang tepat. Perilaku pemblokiran metode ini sama dengan perilaku pemblokiran yang didefinisikan dalam objek.wait. Untuk referensi spesifik, kita dapat menanyakan apakah itu dalam antrian dengan metode terisinya, atau memaksanya ke dalam antrian dengan memanggil metode enqueue, tetapi biasanya jenis penyumbatan ini dilakukan oleh pengumpul sampah.
Referensi virtual dalam antrian referensi dapat digunakan untuk menentukan kapan suatu objek dapat didaur ulang. Kami tidak dapat mengakses objek apa pun melalui referensi virtual, bahkan jika objek dapat dijangkau dengan cara lain, karena metode GET referensi virtual selalu mengembalikan nol. Faktanya, menggunakan referensi virtual untuk menemukan objek yang akan didaur ulang adalah cara yang paling aman, karena referensi yang lemah dan referensi lunak akan dimasukkan ke dalam antrian setelah objek dapat diakhiri, sementara referensi virtual dimasukkan ke dalam antrian setelah objek yang diakhirinya, yaitu dengan benar -benar aman. Jika Anda bisa, referensi virtual harus selalu digunakan, karena referensi lain akan memiliki kemungkinan bahwa finalisasi metode menggunakan objek yang dapat diakhiri.
Pertimbangkan contoh manajer sumber daya yang dapat mengontrol akses ke koleksi sumber daya eksternal. Objek dapat meminta akses ke sumber daya eksternal dan tidak mengakhiri akses sampai operasi selesai, setelah itu mereka harus mengembalikan sumber daya yang digunakan ke manajer sumber daya. Jika sumber daya ini dibagikan, hak penggunaannya akan dilewatkan di antara banyak objek, dan bahkan dapat dilewati di antara banyak utas, sehingga sulit bagi kita untuk menentukan objek mana yang merupakan pengguna terakhir dari sumber daya ini, dan dengan demikian sulit untuk menentukan kode mana yang akan bertanggung jawab untuk mengembalikan sumber daya ini. Untuk menangani situasi ini, manajer sumber daya dapat mencapai daur ulang otomatis sumber daya ini dengan mengaitkan sumber daya ke objek khusus yang disebut kunci. Selama objek utama dapat dijangkau, kami berpikir bahwa sumber ini masih digunakan; Selama objek utama dapat dikumpulkan sebagai sampah, sumber daya akan secara otomatis dirilis. Kode berikut adalah representasi abstrak dari sumber daya di atas:
antarmuka sumber daya {void use (kunci objek, objek ... args); rilis void (); }Ketika sumber daya diperoleh, objek kuncinya harus diberikan kepada manajer sumber daya. Untuk instance sumber daya yang dikembalikan, sumber daya ini hanya dapat digunakan jika mendapatkan kunci yang sesuai. Ini memastikan bahwa setelah kunci didaur ulang, sumber daya yang sesuai tidak dapat lagi digunakan, bahkan jika objek sumber daya yang mewakili sumber daya ini mungkin masih dapat diakses. Perhatikan bahwa objek sumber daya tidak menyimpan referensi yang kuat ke objek utama, yang penting karena ini mencegah objek utama menjadi tidak terjangkau, menghasilkan sumber daya yang tidak dapat dikembalikan. Implementasi sumber daya dapat bersarang di manajer sumber daya:
Private Static Class ResourceImpl mengimplementasikan sumber daya {int keyHash; boolean needrelease = false resourceImpl (tombol objek) {keyhash = system.identityhashCode (key); // = Siapkan sumber daya eksternal Needrelease = true; } Penggunaan public void (Kunci objek, objek ... args) {if (System.IdentityHashCode (key)! = KEYHASH) Lemparkan IlleqalArgumentException baru ("Kunci yang salah" //..gunakan sumber daya} rilis public yang disinkronkan () {if (NeestRelase) {Needrelease = false:/rilis SumberKode hash dari objek utama disimpan ketika sumber daya dibuat, dan setiap kali metode penggunaan dipanggil, ia memeriksa apakah kunci yang sama disediakan. Penggunaan sumber daya yang sebenarnya mungkin juga memerlukan sinkronisasi, tetapi untuk kesederhanaan, kami menghilangkannya di sini. Metode rilis bertanggung jawab untuk melepaskan sumber daya. Ini dapat dipanggil langsung oleh pengguna sumber daya setelah digunakan, atau oleh manajer sumber daya ketika objek kunci tidak lagi dirujuk. Karena kami akan menggunakan utas independen untuk memantau antrian referensi, metode rilis harus disinkronkan dan beberapa panggilan harus diizinkan.
Manajer Sumber Daya yang sebenarnya memiliki formulir berikut:
Publik Kelas Akhir ResourceManager {Final ReferenceQueue
Objek utama dapat berupa objek apa pun, yang memberikan fleksibilitas kepada pengguna sumber daya dibandingkan dengan meminta manajer sumber daya menetapkan objek utama. Ketika metode GetResource dipanggil, objek MPL kerja sumber daya baru akan dibuat, dan kunci yang disediakan untuk metode ini akan diteruskan ke objek sumber daya baru. Kemudian referensi virtual dibuat, dan objek referensialnya adalah kunci yang diteruskan ke metode, dan kemudian referensi virtual ini akan dimasukkan ke dalam antrian referensi manajer sumber daya. Objek referensi dan referensi virtual yang dibuat pada akhirnya akan disimpan dalam tabel pemetaan. Tabel pemetaan ini memiliki dua tujuan: satu adalah untuk menjaga semua objek referensi virtual dapat dijangkau, dan yang lainnya adalah memberikan cara yang nyaman untuk menanyakan objek sumber daya aktual yang terkait dengan setiap referensi virtual. (Alternatifnya adalah untuk subkelas phantomreference dan menyimpan objek sumber daya di bidang.)
Jika objek kunci menjadi tidak terjangkau, manajer sumber daya menggunakan utas "penuai" terpisah untuk memproses sumber daya. Metode shutdown "tutup" penjelajah dengan mengakhiri utas pemanen (sebagai respons terhadap interupsi), menyebabkan metode GetResource untuk melemparkan pengecualian ExllestateException Ille-Lllestate. Dalam desain sederhana ini, referensi apa pun yang mencolokkan antrian setelah penjelajah ditutup tidak akan diproses. Utas Harvester yang sebenarnya adalah sebagai berikut:
Class RESEPREAD memperluas thread {public void run () {// run sampai terputus while (true) {try {referensi ref = queue.remove (); Resource res = null; disinkronkan (ResourceManager.this) {res = refs.get (ref); referensi. hapus (Ref); } res .release (); ref .clear (); } catch (InterruptedException ex) {break; // semuanya selesai}}}}Resturhread adalah kelas internal, dan utas pemanen yang diberikan akan berjalan sampai manajer sumber daya yang terkait dengannya ditutup. Blok utas pada metode hapus sampai referensi virtual yang terkait dengan kunci tertentu dimasukkan ke dalam antrian referensi. Referensi virtual ini dapat memperoleh referensi ke objek sumber daya dari tabel pemetaan, dan kemudian pasangan "kunci-ke-referensi" ini akan dihapus dari tabel pemetaan. Segera setelah itu, metode rilisnya dipanggil pada objek sumber daya untuk melepaskan sumber daya. akhirnya,
Referensi virtual dibersihkan sehingga kunci dapat didaur ulang.
Sebagai alternatif untuk menggunakan utas independen, operasi apa pun yang memanggil metode jajak pendapat pada antrian referensi dan melepaskan semua sumber daya yang kuncinya menjadi tidak terjangkau dapat digantikan dengan metode GetResource ", dan metode shutdow" juga dapat digunakan untuk melakukan operasi jajak pendapat akhir. Semantik manajer sumber daya akan tergantung pada jenis sumber daya aktual dan pola penggunaan sumber daya.
Desain menggunakan antrian referensi jauh lebih dapat diandalkan daripada desain yang menggunakan terminasi secara langsung (terutama referensi virtual). Tetapi kita perlu mengingat bahwa waktu dan lokasi yang tepat dari objek referensi yang dimasukkan ke dalam antrian referensi tidak pasti, kami juga tidak yakin apakah semua referensi yang dapat dimasukkan telah dimasukkan ke dalam antrian referensi ketika aplikasi berakhir. Jika kita perlu memastikan bahwa semua sumber daya dapat dirilis sebelum aplikasi berakhir, kita harus menginstal hook shutdown yang diperlukan atau menggunakan protokol lain yang ditentukan oleh aplikasi untuk memastikan bahwa ini tercapai.