क्या कोई मुझे सुझाव दे सकता है कि मैं एक पैरामीटर को एक धागे में कैसे पारित कर सकता हूं?
साथ ही, यह अनाम वर्गों के लिए कैसे काम करता है?
Consumer<T>
।
क्या कोई मुझे सुझाव दे सकता है कि मैं एक पैरामीटर को एक धागे में कैसे पारित कर सकता हूं?
साथ ही, यह अनाम वर्गों के लिए कैसे काम करता है?
Consumer<T>
।
जवाबों:
आपको रनवेबल ऑब्जेक्ट में कंस्ट्रक्टर में पैरामीटर पास करना होगा:
public class MyRunnable implements Runnable {
public MyRunnable(Object parameter) {
// store parameter for later user
}
public void run() {
}
}
और इसे इस तरह से आह्वान करें:
Runnable r = new MyRunnable(param_value);
new Thread(r).start();
r
में एक ही तर्क होगा, इसलिए यदि हम कई थ्रेड्स के लिए विभिन्न तर्क पास करना चाहते हैं, तो हमें प्रत्येक थ्रेड के लिए वांछित तर्क का उपयोग करके MyThread
एक नया MyThread
उदाहरण बनाने की आवश्यकता होगी । दूसरे शब्दों में, एक धागा ऊपर और चलाने के लिए हमें दो ऑब्जेक्ट बनाने की आवश्यकता है: थ्रेड और MyThread। क्या इसे बुरा माना जाता है, प्रदर्शन-वार?
सवाल संपादन के जवाब में यहाँ बताया गया है कि यह बेनामी वर्गों के लिए कैसे काम करता है
final X parameter = ...; // the final is important
Thread t = new Thread(new Runnable() {
p = parameter;
public void run() {
...
};
t.start();
आपके पास एक वर्ग है जो थ्रेड (या रननेबल को लागू करता है) और एक निर्माता है जिसमें आप पास करना चाहते हैं। फिर, जब आप नया थ्रेड बनाते हैं, तो आपको तर्कों में पास होना होता है, और फिर थ्रेड शुरू होता है, कुछ इस तरह से:
Thread t = new MyThread(args...);
t.start();
Runnable थ्रेड BTW की तुलना में बहुत बेहतर समाधान है। तो मैं पसंद करूंगा:
public class MyRunnable implements Runnable {
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void run() {
}
}
Thread t = new Thread(new MyRunnable(parameter));
t.start();
यह उत्तर मूल रूप से इस समान प्रश्न के समान है: थ्रेड ऑब्जेक्ट में पैरामीटर कैसे पास करें
parameter
सीधे run()
विधि से पहुंचता हूं p
। यह काम करने लगता है। क्या पहले से नकल न करके कुछ सूक्ष्म बहुमूल्य चीज मुझे याद आ रही parameter
है p
?
)
पहले उदाहरण में
final X parameter
से पहले new Runnable()
था, तब तक मैं parameter
अंदर पहुंच सकता था run()
। मुझे अतिरिक्त करने की आवश्यकता नहीं थी p = parameter
।
final
क्या यह उतना महत्वपूर्ण नहीं है; यह पर्याप्त है अगर चर प्रभावी रूप से अंतिम है (इसके बावजूद इसका कोई नुकसान नहीं हुआ है)
एक Runnable या थ्रेड वर्ग के निर्माता के माध्यम से
class MyThread extends Thread {
private String to;
public MyThread(String to) {
this.to = to;
}
@Override
public void run() {
System.out.println("hello " + to);
}
}
public static void main(String[] args) {
new MyThread("world!").start();
}
@Override
?
@Override
स्पष्ट रूप से बताएं कि यह थ्रेड क्लास में अमूर्त पद्धति को ओवरराइड कर रहा है।
यह उत्तर बहुत देर से आता है, लेकिन शायद कोई इसे उपयोगी पाएगा। यह Runnable
नामांकित वर्ग (इनलाइनर्स के लिए आसान) घोषित किए बिना एक पैरामीटर (रों) पास करने के बारे में है :
String someValue = "Just a demo, really...";
new Thread(new Runnable() {
private String myParam;
public Runnable init(String myParam) {
this.myParam = myParam;
return this;
}
@Override
public void run() {
System.out.println("This is called from another thread.");
System.out.println(this.myParam);
}
}.init(someValue)).start();
बेशक आप start
कुछ अधिक सुविधाजनक या उपयुक्त क्षण के निष्पादन को स्थगित कर सकते हैं। और यह आपके ऊपर है कि init
विधि का हस्ताक्षर क्या होगा (इसलिए इसमें अधिक और / या अलग-अलग तर्क हो सकते हैं) और निश्चित रूप से इसका नाम भी, लेकिन मूल रूप से आपको एक विचार मिलता है।
वास्तव में एक ब्लॉक करने के लिए अनाम ब्लॉक के उपयोग के साथ एक अनाम वर्ग को एक पैरामीटर पारित करने का एक और तरीका भी है। इस पर विचार करो:
String someValue = "Another demo, no serious thing...";
int anotherValue = 42;
new Thread(new Runnable() {
private String myParam;
private int myOtherParam;
{
this.myParam = someValue;
this.myOtherParam = anotherValue;
}
@Override
public void run() {
System.out.println("This comes from another thread.");
System.out.println(this.myParam + ", " + this.myOtherParam);
}
}).start();
तो सभी इनिशियलाइज़र ब्लॉक के अंदर होता है।
this.myParam
वास्तव में आवश्यक है? क्या आप केवल निजी चर नहीं छोड़ सकते और बाहरी दायरे से चर का संदर्भ ले सकते हैं? मैं समझता हूं (निश्चित रूप से) इसके कुछ निहितार्थ हैं, जैसे कि धागा शुरू होने के बाद परिवर्तन के लिए खुला होना।
जब आप एक धागा बनाते हैं, तो आपको एक उदाहरण की आवश्यकता होती है Runnable
। एक पैरामीटर में पास करने का सबसे आसान तरीका यह होगा कि इसे कंस्ट्रक्टर के तर्क के रूप में पास किया जाए:
public class MyRunnable implements Runnable {
private volatile String myParam;
public MyRunnable(String myParam){
this.myParam = myParam;
...
}
public void run(){
// do something with myParam here
...
}
}
MyRunnable myRunnable = new myRunnable("Hello World");
new Thread(myRunnable).start();
यदि आप तब पैरामीटर बदलना चाहते हैं जब थ्रेड चल रहा है, तो आप बस अपनी रन करने योग्य कक्षा में एक सेटर विधि जोड़ सकते हैं:
public void setMyParam(String value){
this.myParam = value;
}
एक बार जब आपके पास यह हो जाए, तो आप इस तरह कॉल करके पैरामीटर का मान बदल सकते हैं:
myRunnable.setMyParam("Goodbye World");
बेशक, यदि आप पैरामीटर को बदलने पर एक कार्रवाई को ट्रिगर करना चाहते हैं, तो आपको ताले का उपयोग करना होगा, जिससे चीजें काफी अधिक जटिल हो जाती हैं।
एक धागा बनाने के लिए आप सामान्य रूप से रननेबल का अपना कार्यान्वयन बनाते हैं। इस वर्ग के निर्माता में थ्रेड को पैरामीटर पास करें।
class MyThread implements Runnable{
private int a;
private String b;
private double c;
public MyThread(int a, String b, double c){
this.a = a;
this.b = b;
this.c = c;
}
public void run(){
doSomething(a, b, c);
}
}
आप या तो विस्तार कर सकते हैं या और पैरामीटर प्रदान के रूप में आप चाहते हैं। डॉक्स में सरल उदाहरण हैं । मैं उन्हें यहाँ पोर्ट करूँगा:Thread
class
Runnable
class
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
या तो एक वर्ग लिखें जो रननेबल को लागू करता है, और जो कुछ भी आपको उपयुक्त रूप से परिभाषित कंस्ट्रक्टर में चाहिए उसे पास करें, या एक क्लास लिखें जो उपयुक्त मापदंडों के साथ सुपर () को कॉल करने वाले उपयुक्त रूप से परिभाषित कंस्ट्रक्टर के साथ थ्रेड का विस्तार करता है।
जावा 8 के रूप में, आप मापदंडों को पकड़ने के लिए एक लैम्ब्डा का उपयोग कर सकते हैं जो प्रभावी रूप से अंतिम हैं । उदाहरण के लिए:
final String param1 = "First param";
final int param2 = 2;
new Thread(() -> {
// Do whatever you want here: param1 and param2 are in-scope!
System.out.println(param1);
System.out.println(param2);
}).start();
जावा 8 में आप सीधे कंसीडर एपीआई और थ्रेड के साथ काम करने के लिए उच्च स्तर के प्रतिस्थापन के रूप में lambda
अभिव्यक्ति का उपयोग कर सकते हैं :ExecutorService
newCachedThreadPool()
एक थ्रेड पूल बनाता है जो आवश्यकतानुसार नए थ्रेड बनाता है, लेकिन जब वे उपलब्ध होते हैं तो पहले निर्मित थ्रेड का फिर से उपयोग करेंगे। ये पूल आम तौर पर उन कार्यक्रमों के प्रदर्शन में सुधार करेंगे जो कई अल्पकालिक अतुल्यकालिक कार्यों को निष्पादित करते हैं।
private static final ExecutorService executor = Executors.newCachedThreadPool();
executor.submit(() -> {
myFunction(myParam1, myParam2);
});
executors
Javadocs भी देखें ।
मुझे पता है कि मुझे कुछ साल देर हो गई है, लेकिन मैं इस मुद्दे पर आया और एक अपरंपरागत दृष्टिकोण लिया। मैं इसे एक नई कक्षा बनाये बिना करना चाहता था, इसलिए यह वही है जिसके साथ मैं आया:
int x = 0;
new Thread((new Runnable() {
int x;
public void run() {
// stuff with x and whatever else you want
}
public Runnable pass(int x) {
this.x = x;
return this;
}
}).pass(x)).start();
स्टार्ट () और रन () विधियों से गुजरता हुआ पैरामीटर:
// Tester
public static void main(String... args) throws Exception {
ThreadType2 t = new ThreadType2(new RunnableType2(){
public void run(Object object) {
System.out.println("Parameter="+object);
}});
t.start("the parameter");
}
// New class 1 of 2
public class ThreadType2 {
final private Thread thread;
private Object objectIn = null;
ThreadType2(final RunnableType2 runnableType2) {
thread = new Thread(new Runnable() {
public void run() {
runnableType2.run(objectIn);
}});
}
public void start(final Object object) {
this.objectIn = object;
thread.start();
}
// If you want to do things like setDaemon(true);
public Thread getThread() {
return thread;
}
}
// New class 2 of 2
public interface RunnableType2 {
public void run(Object object);
}
आप रननेबल से एक वर्ग प्राप्त कर सकते हैं, और निर्माण के दौरान (कहते हैं) पैरामीटर को पास कर सकते हैं।
फिर इसे थ्रेड.स्टार्ट (रन करने योग्य आर) का उपयोग करके लॉन्च करें;
तुम्हारा मतलब हैं , जबकि धागा चल रहा है, तो बस बुला धागे में अपने व्युत्पन्न वस्तु के संदर्भ को पकड़, और कॉल उचित सेटर तरीकों (सिंक्रनाइज़ कर जहां उपयुक्त हो)
नहीं, आप इस run()
पद्धति को पैरामीटर नहीं दे सकते । हस्ताक्षर आपको बताता है कि (इसका कोई पैरामीटर नहीं है)। संभवतः ऐसा करने का सबसे आसान तरीका एक उद्देश्य-निर्मित वस्तु का उपयोग करना होगा जो निर्माण में एक पैरामीटर लेता है और इसे अंतिम चर में संग्रहीत करता है:
public class WorkingTask implements Runnable
{
private final Object toWorkWith;
public WorkingTask(Object workOnMe)
{
toWorkWith = workOnMe;
}
public void run()
{
//do work
}
}
//...
Thread t = new Thread(new WorkingTask(theData));
t.start();
एक बार जब आप ऐसा कर लेते हैं - आपको उस वस्तु की डेटा अखंडता से सावधान रहना होगा जिसे आप 'वर्कटैस्क' में पास करते हैं। डेटा अब दो अलग-अलग थ्रेड्स में मौजूद होगा, इसलिए आपको यह सुनिश्चित करना होगा कि यह थ्रेड सेफ है।
एक और विकल्प; यह दृष्टिकोण आपको अतुल्यकालिक फ़ंक्शन कॉल की तरह Runnable आइटम का उपयोग करने देता है। यदि आपके कार्य को परिणाम वापस करने की आवश्यकता नहीं है, उदाहरण के लिए, यह सिर्फ कुछ कार्रवाई करता है तो आपको इस बारे में चिंता करने की आवश्यकता नहीं है कि आप "परिणाम" कैसे पास करते हैं।
यह पैटर्न आपको किसी आइटम का पुन: उपयोग करने देता है, जहां आपको किसी प्रकार की आंतरिक स्थिति की आवश्यकता होती है। जब रचनाकार देखभाल में पैरामीटर (नों) को पारित नहीं किया जाता है, तो मापदंडों तक पहुंच के कार्यक्रमों की मध्यस्थता करने की आवश्यकता होती है। यदि आपके उपयोग-मामले में अलग-अलग कॉलर्स आदि शामिल हैं, तो आपको अधिक जांच की आवश्यकता हो सकती है
public class MyRunnable implements Runnable
{
private final Boolean PARAMETER_LOCK = false;
private X parameter;
public MyRunnable(X parameter) {
this.parameter = parameter;
}
public void setParameter( final X newParameter ){
boolean done = false;
synchronize( PARAMETER_LOCK )
{
if( null == parameter )
{
parameter = newParameter;
done = true;
}
}
if( ! done )
{
throw new RuntimeException("MyRunnable - Parameter not cleared." );
}
}
public void clearParameter(){
synchronize( PARAMETER_LOCK )
{
parameter = null;
}
}
public void run() {
X localParameter;
synchronize( PARAMETER_LOCK )
{
localParameter = parameter;
}
if( null != localParameter )
{
clearParameter(); //-- could clear now, or later, or not at all ...
doSomeStuff( localParameter );
}
}
}
थ्रेड टी = नया थ्रेड (नया MyRunnable (पैरामीटर)); t.start ();
यदि आपको प्रसंस्करण के परिणाम की आवश्यकता है, तो आपको उप-कार्य पूरा होने पर MyRunnable के पूरा होने के समन्वय की भी आवश्यकता होगी। आप कॉल वापस पास कर सकते हैं या बस थ्रेड 't', आदि पर प्रतीक्षा कर सकते हैं।
कॉलबैक उद्देश्यों के लिए, मैं आमतौर पर Runnable
इनपुट पैरामीटर (एस) के साथ अपने स्वयं के सामान्य को लागू करता हूं :
public interface Runnable<TResult> {
void run(TResult result);
}
उपयोग सरल है:
myManager.doCallbackOperation(new Runnable<MyResult>() {
@Override
public void run(MyResult result) {
// do something with the result
}
});
प्रबंधक में:
public void doCallbackOperation(Runnable<MyResult> runnable) {
new AsyncTask<Void, Void, MyResult>() {
@Override
protected MyResult doInBackground(Void... params) {
// do background operation
return new MyResult(); // return resulting object
}
@Override
protected void onPostExecute(MyResult result) {
// execute runnable passing the result when operation has finished
runnable.run(result);
}
}.execute();
}
अपनी कक्षा में एक स्थानीय चर बनाएं extends Thread
या implements Runnable
।
public class Extractor extends Thread {
public String webpage = "";
public Extractor(String w){
webpage = w;
}
public void setWebpage(String l){
webpage = l;
}
@Override
public void run() {// l is link
System.out.println(webpage);
}
public String toString(){
return "Page: "+webpage;
}}
इस तरह, आप एक चर पास कर सकते हैं जब आप इसे चलाते हैं।
Extractor e = new Extractor("www.google.com");
e.start();
उत्पादन:
"www.google.com"