Dalam artikel sebelumnya, kami menganalisis bagaimana kelas proxy dihasilkan di dalam kelas proxy. Kami melihat bahwa mekanisme cache digunakan di dalam proxy. Jika kelas proxy dapat ditemukan di cache berdasarkan kelas loader dan antarmuka yang disediakan, kelas proxy akan dikembalikan secara langsung. Kalau tidak, pabrik proxyclassFactory akan dipanggil untuk menghasilkan kelas proxy. Cache yang digunakan di sini adalah cache sekunder, dan kunci cache tingkat pertama dihasilkan berdasarkan class loader, dan kunci cache tingkat kedua dihasilkan berdasarkan array antarmuka. Kami akan secara langsung memposting kode untuk menjelaskan mekanisme internal spesifik secara rinci.
// Referensi Referensi Antrian Private ReferenceQueue <K> Refqueue = ReferenceQueue baru <> (); // Implementasi cache yang mendasari, kuncinya adalah cache tingkat pertama dan nilainya adalah cache tingkat kedua. Untuk mendukung NULL, jenis utama peta diatur ke ObjectPrivate Final ConcurrentMap <Object, ConcurrentMap <Object, Supplier <V>>> MAP = ConcurrenthashMap baru <> (); // ReverSemap mencatat apakah semua generator kelas proxy tersedia. Ini untuk mengimplementasikan mekanisme kadaluwarsa cache final concurrentMap <pemasok <v>, boolean> reversemap = concurrenthashmap baru <> (); // pabrik yang menghasilkan kunci cache sekunder, final cacate cacecory cace,? BiFunction<K, P, V> valueFactory;//Constructor, the factory that generates the secondary cache key and the factory that generates the secondary cache value public WeakCache(BiFunction<K, P, ?> subKeyFactory, BiFunction<K, P, V> valueFactory) { this.subKeyFactory = Objects.requireNonNull(subKeyFactory); this.valueFactory = objects.requirenonnull (valueFactory);}Pertama, mari kita lihat variabel anggota dan konstruktor lemah. Implementasi internal cache Lemah Lemah diselesaikan melalui ConcurrentMap. Peta variabel anggota adalah implementasi yang mendasari cache sekunder. Reversemap adalah untuk mengimplementasikan mekanisme kadaluwarsa cache. Subkeyfactory adalah pabrik generasi dari kunci cache sekunder. Itu dilewatkan melalui konstruktor. Nilai yang dilewati di sini adalah KeyFactory dari kelas proxy, dan penilai adalah pabrik generasi dari nilai cache sekunder. Itu dilewatkan melalui konstruktor. ProxyClassFactory kelas proxy dilewati di sini. Selanjutnya, mari kita lihat metode GET lemah.
public v get (K key, parameter p) {// Antarmuka yang harus diterapkan di sini tidak dapat menjadi objek kosong.requirenonnull (parameter); // hapus cache expungestaleentries (); // Bungkus ClassLoader ke CacheKey sebagai kunci untuk objek cache tingkat pertama CacheKey = CacheKey.VALUEOF (Key, REFQUEUE); // Dapatkan cache sekunder ConcurrentMap <objek, pemasok <v>> valuesMap = Map.get (CacheKey); // Jika nilai yang sesuai tidak diperoleh berdasarkan ClassLoader if (valuesMap == null) {// Masukkan ke dalam CAS, jika tidak ada, masukkan, jika tidak mengembalikan nilai asli concurrentMap <objek, pemasok <v>> oldvaluesmap = peta.putifabsent (CacheKey, valueSmap = concurrenthashmap <> map. // Jika OldValuesMap memiliki nilai, itu berarti bahwa penempatan gagal jika (oldValuesMap! = Null) {valuesmap = oldValuesMap; }} // Buat kunci cache tingkat kedua berdasarkan array antarmuka yang diimplementasikan oleh kelas proxy, dibagi menjadi key0, key1, key2, objek keyx subkey = objects.requirenonnull (subkeyfactory.apply (key, parameter)); // Nilai cache sekunder diperoleh melalui subkey. Pemasok <v> pemasok = valuesmap.get (subkey); Pabrik Pabrik = NULL; // Loop ini menyediakan mekanisme pemungutan suara. Jika kondisinya salah, terus coba lagi sampai kondisinya benar saat (true) {// Jika nilainya diambil melalui Subkey tidak kosong jika (pemasok! = NULL) {// Di sini pasokan mungkin merupakan pabrik atau cachevalue // tidak ada penilaian yang dibuat di sini, tetapi verifikasi dalam metode GET dari kelas implementasi pemasok value value = get () (); if (value! = null) {nilai kembali; }} if (factory == null) {// Buat instance pabrik baru sebagai nilai yang sesuai dari subkey factory = pabrik baru (kunci, parameter, subkey, valuesmap); } if (pemasok == null) {// Jadi di sini berarti bahwa subkey tidak memiliki nilai yang sesuai, menempatkan pabrik sebagai nilai subkey di pemasok = valuesmap.putifabsent (subkey, pabrik); if (pemasok == null) {// Jadi di sini berarti pabrik berhasil ditempatkan di pemasok cache = pabrik; } // Sebaliknya, utas lain dapat memodifikasi nilai selama periode tersebut, maka kami tidak lagi terus menetapkan nilai ke subkey, tetapi mengeluarkannya dan menggunakannya secara langsung} else {// selama periode ini, utas lain mungkin telah memodifikasi nilai, jadi ganti nilai asli jika (nilai -nilaiMap.replace (Subkey, Pemasok, Factory)) {// Berhasil mengganti Factorymap.replace (Subkey, Pemasok, FACTORY)) {// GABUNG TERKAIRAN THE SURIGN FACTORY (SUMPLAER (SUBLEY, FACTORY) {// Ganti Factory Berhasil } else {// ganti gagal, terus gunakan pemasok nilai asli = valuesmap.get (subkey); }}}}Metode GET Lemah Lemari tidak disinkronkan dengan kunci, jadi bagaimana cara mencapai keamanan utas? Karena semua variabel anggota yang dimodifikasi menggunakan ConcurrentMap, kelas ini aman. Oleh karena itu, ia mendelegasikan keamanan utasnya sendiri ke ConcurrentMap, dan metode GET mengurangi blok kode sinkronisasi sebanyak mungkin, yang secara efektif dapat meningkatkan kinerja Lemah Lemah. Kami melihat bahwa ClassLoader adalah kunci cache Level 1, sehingga kami dapat memfilternya terlebih dahulu menurut ClassLoader, karena kelas yang dimuat oleh classloader yang berbeda berbeda. Kemudian menggunakan array antarmuka untuk menghasilkan kunci cache sekunder. Di sini ia memiliki beberapa optimisasi. Karena sebagian besar kelas menerapkan satu atau dua antarmuka, kunci cache sekunder dibagi menjadi KEY0, KEY1, KEY2, dan KEYX. Key0 ke KEY2 berarti bahwa antarmuka 0 hingga 2 diimplementasikan, dan KeyX berarti bahwa 3 atau lebih antarmuka diimplementasikan. Bahkan, kebanyakan dari mereka hanya akan menggunakan KEY1 dan KEY2. Pabrik generasi dari kunci -kunci ini ada di kelas proxy, dan pabrik utama dilewatkan melalui konstruktor Lemah. Nilai cache tingkat kedua di sini adalah contoh pabrik, dan nilai akhir dari kelas proxy diperoleh melalui pabrik pabrik.
Private Final Class Factory mengimplementasikan pemasok <V> {// Kunci Cache Level 1, Hasilkan Kunci K Private Kas Menurut ClassLoader; // Antarmuka Array Private Final P Parameter yang diimplementasikan oleh kelas proxy; // Kunci cache Level 2, menghasilkan subkey objek akhir pribadi sesuai dengan array antarmuka; // level 2 cache private concurrentmap <objek, pemasok <v>> valuesmap; Pabrik (Key K, Parameter P, Subkey Objek, ConcurrentMap <Object, Pemasok <V>> ValuesMap) {this.key = key; this.parameter = parameter; this.subkey = subkey; this.valuesmap = valuesmap; } @Override Publik disinkronkan v get () {// Di sini saya pergi ke cache sekunder lagi untuk mendapatkan pemasok untuk memverifikasi apakah itu adalah pemasok pabrik itu sendiri <v> pemasok = valuesmap.get (subkey); if (pemasok! = ini) {// Di sini saya memverifikasi apakah pemasok adalah instance pabrik itu sendiri, jika tidak, kembalikan nol dan biarkan penelepon terus polling dan coba lagi // selama periode tersebut, pemasok dapat diganti dengan cachevalue, atau dihapus dari cache sekunder karena kegagalan untuk menghasilkan kelas proxy; } V value = null; Coba {// Delegasi ValueFactory untuk menghasilkan kelas proxy, di sini nilai kelas proxy akan dihasilkan melalui proxyclassFactory = objek.Requirenonnull yang masuk (valueFactory.Amply (kunci, parameter)); } akhirnya {// Jika pembuatan kelas proxy gagal, hapus cache sekunder ini if (value == null) {valuesmap.remove (subkey, this); }} // Hanya nilai nilai yang tidak kosong dapat mencapai di sini nilai menegaskan! = Null; // kelas proxy Cachevalue <V> Cachevalue = Cachevalue baru <> (nilai); // Masukkan cachevalue yang dikemas ke dalam cache sekunder. Operasi ini harus berhasil, jika tidak, kesalahan akan dilaporkan jika (valuesmap.replace (subkey, ini, cachevalue)) {// Setelah berhasil memasukkan cache ke dalam cache sekunder, tandai reversemap.put (cachevalue, boolean.true); } else {throw new AssertionError ("tidak boleh mencapai di sini"); } // Akhirnya mengembalikan nilai pengembalian kelas proxy yang tidak dibungkus dengan referensi lemah; }}Mari kita lihat pabrik kelas internal pabrik lagi, dan kita dapat melihat bahwa metode GET -nya disinkronkan menggunakan kata kunci yang disinkronkan. Setelah melakukan metode GET, pertama verifikasi apakah pemasok yang sesuai dengan Subkey adalah pabrik itu sendiri. Jika tidak, itu akan mengembalikan NULL, dan Metode Get Lemah akan terus mencoba lagi. Jika memang pabrik itu sendiri, maka proxyclassFactory akan didelegasikan untuk menghasilkan kelas proxy, yang dilewatkan saat membangun lemah. Jadi di sini menjelaskan mengapa pabrik internal proxyclassfactory di proxy dipanggil untuk menghasilkan kelas proxy pada akhirnya. Setelah menghasilkan kelas proxy, ia menggunakan referensi yang lemah untuk membungkusnya dan meletakkannya di Reversemap, dan akhirnya mengembalikan kelas proxy asli.
Sejauh ini, kami telah mengungkapkan secara terperinci implementasi cache lemah termasuk cache tingkat pertama dan prinsip-prinsip implementasi cache tingkat kedua, serta prinsip menghasilkan kunci cache tingkat kedua, dan bagaimana ia menyebut proxyclassFactory untuk menghasilkan kelas proxy pada akhirnya. Pada artikel berikutnya, kami akan masuk ke kelas proxygenerator untuk melihat proses pembuatan bytecode dari kelas proxy spesifik.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.