Java Language
ThreadLocal
खोज…
टिप्पणियों
बेस्ट वस्तुओं जो अन्यथा एक फोन लागू दौरान आंतरिक पर निर्भर करते हैं, लेकिन राज्यविहीन हैं, जैसे के लिए इस्तेमाल किया SimpleDateFormat
, Marshaller
के लिए Random
ThreadLocal उपयोग, का उपयोग कर विचार ThreadLocalRandom
थ्रेडलोकल जावा 8 फंक्शनल इनिशियलाइज़ेशन
public static class ThreadLocalExample
{
private static final ThreadLocal<SimpleDateFormat> format =
ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyyMMdd_HHmm"));
public String formatDate(Date date)
{
return format.get().format(date);
}
}
मूल थ्रेडलोक का उपयोग
जावा ThreadLocal
का उपयोग थ्रेड स्थानीय चर बनाने के लिए किया जाता है। यह ज्ञात है कि ऑब्जेक्ट के थ्रेड्स यह चर हैं, इसलिए चर थ्रेड सुरक्षित नहीं है। हम थ्रेड सेफ्टी के लिए सिंक्रोनाइज़ेशन का उपयोग कर सकते हैं लेकिन अगर हम सिंक्रोनाइज़ेशन से बचना चाहते हैं, तो थ्रेडलोक हमें वैरिएबल बनाने की अनुमति देता है जो थ्रेड के लिए स्थानीय हैं, यानी केवल वह थ्रेड उन वैरिएबल्स को पढ़ या लिख सकता है, इसलिए अन्य थ्रेड्स कोड के एक ही टुकड़े को निष्पादित करते हैं। एक-दूसरे के थ्रेडलोक चर का उपयोग करने में सक्षम नहीं होंगे।
यह usedwe उपयोग कर सकते हैं हो सकता है ThreadLocal
चर। उन स्थितियों में जहां आपके पास एक वेब सेवा में उदाहरण के लिए थ्रेड पूल है। उदाहरण के लिए, प्रत्येक अनुरोध के लिए हर बार एक SimpleDateFormat
ऑब्जेक्ट बनाना समय लेने वाली है और एक स्टेटिक नहीं बनाया जा सकता है क्योंकि SimpleDateFormat
थ्रेड सुरक्षित नहीं है, इसलिए हम एक थ्रेडलॉक बना सकते हैं ताकि हम SimpleDateFormat
बनाने के ओवरहेड के बिना थ्रेड सुरक्षित संचालन कर SimpleDateFormat
समय।
कोड के नीचे का टुकड़ा दिखाता है कि इसका उपयोग कैसे किया जा सकता है:
प्रत्येक थ्रेड में स्वयं ThreadLocal
वैरिएबल होता है और वे डिफ़ॉल्ट मान प्राप्त करने या थ्रेड के लिए स्थानीय मान को बदलने के लिए इसे get()
और set()
विधियों का उपयोग कर सकते हैं।
ThreadLocal
इंस्टेंस आमतौर पर निजी स्टेटिक फील्ड होते हैं जो एक थ्रेड के साथ राज्य को जोड़ना चाहते हैं।
यहाँ जावा प्रोग्राम में थ्रेडलोकल का उपयोग दिखाते हुए एक छोटा सा उदाहरण है और यह साबित करता है कि हर थ्रेड में ThreadLocal
वैरिएबल की अपनी प्रति है।
package com.examples.threads;
import java.text.SimpleDateFormat;
import java.util.Random;
public class ThreadLocalExample implements Runnable{
// SimpleDateFormat is not thread-safe, so give one to each thread
// SimpleDateFormat is not thread-safe, so give one to each thread
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
@Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
public static void main(String[] args) throws InterruptedException {
ThreadLocalExample obj = new ThreadLocalExample();
for(int i=0 ; i<10; i++){
Thread t = new Thread(obj, ""+i);
Thread.sleep(new Random().nextInt(1000));
t.start();
}
}
@Override
public void run() {
System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
formatter.set(new SimpleDateFormat());
System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
}
}
आउटपुट:
Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a
जैसा कि हम आउटपुट से देख सकते हैं कि थ्रेड -0 ने फॉर्मैटर के मूल्य को बदल दिया है, लेकिन फिर भी थ्रेड -2 डिफ़ॉल्ट फॉर्मैटर प्रारंभिक मूल्य के समान है।
एक साझा वस्तु के साथ कई धागे
इस उदाहरण में हमारे पास केवल एक ही वस्तु है लेकिन इसे विभिन्न थ्रेड्स पर / निष्पादित के बीच साझा किया गया है। राज्य को बचाने के लिए खेतों का साधारण उपयोग संभव नहीं होगा क्योंकि दूसरा धागा वह भी देखेगा (या शायद नहीं देखेगा)।
public class Test {
public static void main(String[] args) {
Foo foo = new Foo();
new Thread(foo, "Thread 1").start();
new Thread(foo, "Thread 2").start();
}
}
फू में हम शून्य से शुरू होने की गिनती करते हैं। राज्य को एक क्षेत्र में सहेजने के बजाय हम अपने वर्तमान नंबर को थ्रेडलोक ऑब्जेक्ट में संग्रहीत करते हैं जो कि सांख्यिकीय रूप से सुलभ है। ध्यान दें कि इस उदाहरण में सिंक्रोनाइज़ेशन थ्रेडलोक के उपयोग से संबंधित नहीं है, बल्कि एक बेहतर कंसोल आउटपुट सुनिश्चित करता है।
public class Foo implements Runnable {
private static final int ITERATIONS = 10;
private static final ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
@Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
synchronized (threadLocal) {
//Although accessing a static field, we get our own (previously saved) value.
int value = threadLocal.get();
System.out.println(Thread.currentThread().getName() + ": " + value);
//Update our own variable
threadLocal.set(value + 1);
try {
threadLocal.notifyAll();
if (i < ITERATIONS - 1) {
threadLocal.wait();
}
} catch (InterruptedException ex) {
}
}
}
}
}
आउटपुट से हम देख सकते हैं कि प्रत्येक थ्रेड स्वयं के लिए मायने रखता है और दूसरे के मूल्य का उपयोग नहीं करता है:
Thread 1: 0
Thread 2: 0
Thread 1: 1
Thread 2: 1
Thread 1: 2
Thread 2: 2
Thread 1: 3
Thread 2: 3
Thread 1: 4
Thread 2: 4
Thread 1: 5
Thread 2: 5
Thread 1: 6
Thread 2: 6
Thread 1: 7
Thread 2: 7
Thread 1: 8
Thread 2: 8
Thread 1: 9
Thread 2: 9