Ya, itu aman dan direkomendasikan.
Satu-satunya peringatan dari halaman yang Anda referensikan adalah Anda tidak dapat memodifikasi konfigurasi mapper setelah dibagikan; tetapi Anda tidak mengubah konfigurasi sehingga tidak masalah. Jika Anda memang perlu mengubah konfigurasi, Anda akan melakukannya dari blok statis dan itu akan baik-baik saja.
EDIT : (2013/10)
Dengan 2.0 dan di atas, di atas dapat ditambah dengan mencatat bahwa ada cara yang lebih baik: penggunaan ObjectWriter
dan ObjectReader
objek, yang dapat dibangun oleh ObjectMapper
. Mereka sepenuhnya tidak dapat diubah, thread-safe, yang berarti bahwa bahkan secara teori tidak mungkin menyebabkan masalah keamanan thread (yang dapat terjadi dengan ObjectMapper
jika kode mencoba mengkonfigurasi ulang instance).
ObjectMapper
masih aman setelahObjectMapper#setDateFormat()
dipanggil. Diketahui bahwaSimpleDateFormat
ini tidak aman untuk thread , jadiObjectMapper
tidak akan kecuali itu mengklon misalnyaSerializationConfig
sebelum masing-masingwriteValue()
(saya ragu). Bisakah Anda menghilangkan rasa takut saya?DateFormat
memang dikloning di bawah tenda. Kecurigaan bagus di sana, tetapi Anda dilindungi. :)ObjectMapper
? Metode diberi namawriter()
danreader()
(dan beberapareaderFor()
,writerFor()
).mapper.with()
panggilan (karena "dengan" di Jackson menyiratkan pembangunan instance baru, dan eksekusi thread-safe). Tetapi mengenai perubahan konfigurasi: tidak ada pemeriksaan yang dilakukan, jadi akses konfigurasiObjectMapper
harus dijaga. Adapun "salin ()": ya, itu membuat salinan baru yang baru yang mungkin sepenuhnya (kembali) dikonfigurasi, sesuai dengan aturan yang sama: konfigurasikan sepenuhnya terlebih dahulu, kemudian gunakan, dan itu baik-baik saja. Ada biaya non-sepele yang terkait (karena salinan tidak dapat menggunakan penangan dalam cache apa pun), tetapi ini adalah cara yang aman, ya.Meskipun ObjectMapper aman untuk di-thread, saya sangat tidak menyarankan untuk mendeklarasikannya sebagai variabel statis, terutama dalam aplikasi multithreaded. Bukan karena itu adalah praktik yang buruk, tetapi karena Anda menghadapi risiko besar mengalami kebuntuan. Saya menceritakannya dari pengalaman saya sendiri. Saya membuat aplikasi dengan 4 utas identik yang mendapatkan dan memproses data JSON dari layanan web. Aplikasi saya sering mengulur-ulur pada perintah berikut, menurut thread dump:
Selain itu, kinerjanya juga tidak bagus. Ketika saya mengganti variabel statis dengan variabel berbasis instance, mengulur-ulur menghilang dan kinerja empat kali lipat. Yaitu 2,4 juta dokumen JSON diproses dalam 40 menit.56sec., Bukan 2.5 jam sebelumnya.
sumber
ObjectMapper
instance untuk setiap instance kelas dapat mencegah kunci tetapi bisa sangat berat pada GC nanti (bayangkan satu instance ObjectMapper untuk setiap instance dari kelas yang Anda buat). Pendekatan jalur tengah dapat, alih-alih menyimpan hanya satuObjectMapper
instance statis (publik) di seluruh aplikasi, Anda dapat mendeklarasikan instance statis (pribadi)ObjectMapper
di setiap kelas . Ini akan mengurangi kunci global (dengan mendistribusikan load-bijaksana), dan tidak akan membuat objek baru juga, karenanya menyalakan GC juga.ObjectPool
adalah cara terbaik yang dapat Anda lakukan - dengan demikian memberikan yang terbaikGC
danLock
pertunjukan. Anda dapat merujuk ke tautan berikut untukObjectPool
implementasi apache-common . commons.apache.org/proper/commons-pool/api-1.6/org/apache/…ObjectMapper
suatu tempat, tetapi hanya mendapatkanObjectReader
/ObjectWriter
contoh (melalui metode pembantu), mempertahankan referensi ke yang ada di tempat lain (atau panggilan dinamis). Objek pembaca / penulis ini tidak hanya sepenuhnya konfigurasi ulang WRT yang aman, tetapi juga sangat ringan (contoh instance mapper). Jadi menjaga ribuan referensi tidak menambah banyak penggunaan memori.Meskipun aman untuk mendeklarasikan ObjectMapper statis dalam hal keamanan utas, Anda harus menyadari bahwa membangun variabel Objek statis di Jawa dianggap praktik buruk. Untuk detail lebih lanjut, lihat Mengapa variabel statis dianggap jahat? (dan jika Anda mau, jawabanku )
Singkatnya, statika harus dihindari karena menyulitkan untuk menulis tes unit ringkas. Misalnya, dengan ObjectMapper final statis, Anda tidak dapat menukar keluar serialisasi JSON untuk kode dummy atau larangan.
Selain itu, final statis mencegah Anda mengkonfigurasi ulang ObjectMapper saat runtime. Anda mungkin tidak membayangkan alasan untuk itu sekarang, tetapi jika Anda mengunci diri Anda sendiri ke dalam pola final statis, tidak akan merusak classloader yang akan membuat Anda menginisialisasi ulang itu.
Dalam kasus ObjectMapper baik-baik saja, tetapi secara umum itu adalah praktik yang buruk dan tidak ada keuntungan dibandingkan menggunakan pola tunggal atau inversi-of-control untuk mengelola objek berumur panjang Anda.
sumber
readerFor
danwriterFor
yang membuatObjectReader
danObjectWriter
contoh pada permintaan. Jadi saya akan mengatakan meletakkan mapper dengan konfigurasi awal di suatu tempat statis, lalu dapatkan pembaca / penulis dengan konfigurasi per-kasus saat Anda membutuhkannya?Trik yang saya pelajari dari PR ini jika Anda tidak ingin mendefinisikannya sebagai variabel final statis tetapi ingin menyimpan sedikit overhead dan menjamin thread aman.
kredit kepada penulis.
sumber
ObjectMapper
akan melekat pada utas yang mungkin menjadi bagian dari kolam.com.fasterxml.jackson.databind.type.TypeFactory._hashMapSuperInterfaceChain (HierarchicType)
Metode _hashMapSuperInterfaceChain di kelas com.fasterxml.jackson.databind.type.TypeFactory disinkronkan. Saya melihat pertengkaran pada saat yang sama pada beban tinggi.
Mungkin alasan lain untuk menghindari ObjectMapper statis
sumber
TypeReference
adalah hal yang agak mahal untuk digunakan: jika mungkin, menyelesaikannya untukJavaType
menghindari sedikit pemrosesan (TypeReference
s tidak dapat - sayangnya - di-cache karena alasan bahwa saya tidak akan menggali ke sini), karena mereka "sepenuhnya teratasi" (super-type, generic typing dll).