synchronizedजावा कीवर्ड कैसे काम करता है
जब आप जोड़ते हैं synchronized कीवर्ड को स्टैटिक विधि से , तो विधि को एक बार में केवल एक थ्रेड द्वारा बुलाया जा सकता है।
आपके मामले में, हर विधि कॉल करेगी:
- कोई नया बनाएं
SessionFactory
- कोई नया बनाएं
Session
- इकाई लाना
- कॉलर को इकाई वापस लौटाएं
हालाँकि, ये आपकी आवश्यकताएं थीं:
- मैं चाहता हूँ कि यह एक ही DB उदाहरण के लिए जानकारी तक पहुँच को रोकने के लिए है।
- रोकने
getObjectByIdजब यह एक विशेष वर्ग से पुकारा जाता है सभी वर्गों के लिए बुलाया जा रहा है
इसलिए, भले ही getObjectByIdविधि थ्रेड-सुरक्षित हो, कार्यान्वयन गलत है।
SessionFactory सर्वोत्तम प्रथाएं
यह SessionFactoryथ्रेड-सुरक्षित है, और इसे बनाने के लिए एक बहुत महंगी वस्तु है क्योंकि इसमें इकाई वर्गों को पार्स करने और आंतरिक इकाई मेटामोडियम प्रतिनिधित्व का निर्माण करने की आवश्यकता है।
इसलिए, आपको SessionFactoryहर getObjectByIdविधि कॉल पर नहीं बनाना चाहिए ।
इसके बजाय, आपको इसके लिए एक एकल उदाहरण बनाना चाहिए।
private static final SessionFactory sessionFactory = new Configuration()
.configure()
.buildSessionFactory();
Sessionहमेशा बंद किया जाना चाहिए
आप बंद नहीं किया Sessionएक में finallyब्लॉक, और इस डाटाबेस संसाधन लीक कर सकते हैं अगर एक अपवाद जब इकाई लोड हो रहा है फेंक दिया है।
Session.loadJavaDoc एक HibernateExceptionइकाई में डेटाबेस में नहीं पाया जा सकता है, तो विधि के अनुसार ।
यदि उदाहरण मौजूद है ( get()इसके बजाय उपयोग ) यह निर्धारित करने के लिए आपको इस विधि का उपयोग नहीं करना चाहिए । इसका उपयोग केवल उस उदाहरण को प्राप्त करने के लिए करें जिसे आप मानते हैं कि मौजूद है, जहां गैर-अस्तित्व एक वास्तविक त्रुटि होगी।
इसलिए आपको इस तरह से इसे finallyबंद करने के लिए एक ब्लॉक का उपयोग करने की आवश्यकता है Session:
public static synchronized Object getObjectById (Class objclass, Long id) {
Session session = null;
try {
session = sessionFactory.openSession();
return session.load(objclass, id);
} finally {
if(session != null) {
session.close();
}
}
}
बहु-धागा पहुंच को रोकना
आपके मामले में, आप यह सुनिश्चित करना चाहते थे कि केवल एक धागा उस विशेष इकाई तक पहुंच प्राप्त करे।
लेकिन synchronizedकीवर्ड केवल दो थ्रेड को कॉल करने से रोकता हैgetObjectById समवर्ती है। यदि दो धागे एक के बाद एक इस विधि को कहते हैं, तो आपके पास इस इकाई का उपयोग करने वाले दो धागे होंगे।
इसलिए, यदि आप किसी दिए गए डेटाबेस ऑब्जेक्ट को लॉक करना चाहते हैं तो कोई अन्य धागा इसे संशोधित नहीं कर सकता है, तो आपको डेटाबेस लॉक का उपयोग करने की आवश्यकता है।
synchronizedकीवर्ड केवल एक JVM में काम करता है। यदि आपके पास कई वेब नोड्स हैं, तो यह मल्टीपल जेवीएम के मल्टी-थ्रेड एक्सेस को नहीं रोक पाएगा।
DB को परिवर्तनों को लागू करते समय आपको क्या करने की आवश्यकता है, इसका उपयोग करें LockModeType.PESSIMISTIC_READयाLockModeType.PESSIMISTIC_WRITE इस तरह करें:
Session session = null;
EntityTransaction tx = null;
try {
session = sessionFactory.openSession();
tx = session.getTransaction();
tx.begin();
Post post = session.find(
Post.class,
id,
LockModeType.LockModeType.PESSIMISTIC_READ
);
post.setTitle("High-Performance Java Perisstence");
tx.commit();
} catch(Exception e) {
LOGGER.error("Post entity could not be changed", e);
if(tx != null) {
tx.rollback();
}
} finally {
if(session != null) {
session.close();
}
}
तो यही वह है जो मैंने किया:
- मैंने एक नया बनाया
EntityTransactionऔर एक नया डेटाबेस लेनदेन शुरू किया
- मैंने
Postसंबद्ध डेटाबेस रिकॉर्ड पर ताला लगाते हुए इकाई को लोड किया
- मैंने बदल दिया
Post इकाई को और लेनदेन को प्रतिबद्ध किया
Exceptionफेंके जाने की स्थिति में , मैंने लेन-देन वापस कर दिया
एसीआईडी और डेटाबेस लेनदेन के बारे में अधिक जानकारी के लिए, इस लेख को भी देखें।