एक पैरामीटर के साथ चलाने योग्य?


178

मुझे एक "रननेबल की आवश्यकता है जो एक पैरामीटर को स्वीकार करता है" हालांकि मुझे पता है कि इस तरह के रननेबल वास्तव में मौजूद नहीं है।

यह मेरे ऐप और / या मेरे थके हुए मस्तिष्क में एक मानसिक अवरोध के डिजाइन में मूलभूत दोष की ओर इशारा कर सकता है, इसलिए मैं यहाँ पर कुछ सलाह प्राप्त करने की उम्मीद कर रहा हूँ कि मौलिक OO सिद्धांतों का उल्लंघन किए बिना निम्नलिखित की तरह कुछ कैसे पूरा किया जाए :

  private Runnable mOneShotTask = new Runnable(String str) {
    public void run(String str) {
       someFunc(str);
    }
  };  

किसी भी विचार कैसे ऊपर की तरह कुछ पूरा करने के लिए?


7
अब आप उपयोग कर सकते हैं Consumer<T>
एलेक्स78191

1
मैंने इस प्रश्न के विभिन्न उत्तर पढ़े हैं। यह मुझे अजीब लगता है कि किसी ने यह नहीं बताया कि आप अपने प्रोजेक्ट को रनवेबल्स में जोड़ सकते हैं, जिसकी आपको ज़रूरत है (एक, दो, तीन या अधिक आर्ग्स के साथ) बस एक उपयुक्त इंटरफ़ेस जोड़ रहा है। मैंने यहाँ रुचि रखने वाले व्यक्ति के लिए एक टिप्पणी दी है: gist.github.com/jsfan3/3a66e711fd0fd233c5e4c467184adb7a
Francesco

यह "मैं एक जावा थ्रेड के लिए एक पैरामीटर कैसे पारित कर सकता हूं" के लिए एक डुप्लिकेट नहीं है। और आधुनिक उत्तर यह है, जैसे @ अलेक्सांज़ Consumer<T>
इपगा

जवाबों:


228

खैर यह लगभग 9 साल हो गया है क्योंकि मैंने इसे मूल रूप से पोस्ट किया है और ईमानदार होने के लिए, जावा ने तब से कुछ सुधार किया है। मैं अपना मूल उत्तर नीचे छोड़ दूंगा, लेकिन लोगों को इसमें क्या करना है, इसकी कोई आवश्यकता नहीं है। 9 साल पहले, कोड समीक्षा के दौरान मैंने सवाल किया होगा कि उन्होंने ऐसा क्यों किया और शायद इसे मंजूरी दे दी, शायद नहीं। आधुनिक लैम्ब्डा उपलब्ध होने के साथ, यह एक गैर-अनुमानित दृष्टिकोण की सिफारिश करने वाले इस तरह के अत्यधिक मतदान के जवाब के लिए गैर जिम्मेदाराना है (जो कि, सभी निष्पक्षता में, इसके साथ शुरू करने के लिए संदिग्ध था ...) आधुनिक जावा में, उस कोड की समीक्षा तुरंत अस्वीकार कर दी जाएगी, और यह होगा सुझाव दिया:

void foo(final String str) {
    Thread t = new Thread(() -> someFunc(str));
    t.start();
}

पहले की तरह, उस धागे को सार्थक तरीके से संभालने जैसे विवरण पाठक को एक अभ्यास के रूप में छोड़ दिया जाता है। लेकिन इसे स्पष्ट रूप से कहने के लिए, यदि आप लैम्ब्डा का उपयोग करने से डरते हैं, तो आपको बहु-थ्रेडेड सिस्टम से भी अधिक डरना चाहिए।

मूल उत्तर, सिर्फ इसलिए:

आप विधि में एक वर्ग को सही घोषित कर सकते हैं

void Foo(String str) {
    class OneShotTask implements Runnable {
        String str;
        OneShotTask(String s) { str = s; }
        public void run() {
            someFunc(str);
        }
    }
    Thread t = new Thread(new OneShotTask(str));
    t.start();
}

आप सभी को धन्यवाद! सभी सुझाए गए समाधान एक ही दृष्टिकोण की ओर इशारा करते हैं लेकिन मैं केवल एक को ही स्वीकार कर सकता हूं। मैं बहुत थक गया हूँ खुद को इस के साथ आने में सक्षम नहीं किया जा रहा है। सभी को +1।
uTubeFan

18
दरअसल, ज्यादातर लोग नहीं जानते कि आप एक विधि के अंदर एक वर्ग की घोषणा कर सकते हैं। कुछ इसे घटिया शैली मानते हैं। मुझे लगता है कि यह स्वाद की बात है। :)
corsiKa

3
सार्वजनिक इंटरफ़ेस परिणामी <T> {सार्वजनिक शून्य रन (टी परिणाम); }
रोमन एम

46

आप इसे किसी फ़ंक्शन में रख सकते हैं।

String paramStr = "a parameter";
Runnable myRunnable = createRunnable(paramStr);

private Runnable createRunnable(final String paramStr){

    Runnable aRunnable = new Runnable(){
        public void run(){
            someFunc(paramStr);
        }
    };

    return aRunnable;

}

(जब मैंने इसका उपयोग किया था, तो मेरा पैरामीटर एक पूर्णांक आईडी था, जिसका उपयोग मैंने आईडी के हैशमैप बनाने के लिए किया था -> myununnables। इस तरह, मैं हैंडलर में विभिन्न myRunnable ऑब्जेक्ट्स को पोस्ट / हटाने के लिए हैशमैप का उपयोग कर सकता हूं।)


3
कोड साझा करने के लिए धन्यवाद - मुझे अच्छा लगता है जब लोग ऐसा करते हैं, बजाय सिर्फ भुनभुनाने के। एक प्रश्न - मेमोरी लीकिंग की बात आने पर यह ठीक है? आपके द्वारा पास किए गए सभी संदर्भों का सही तरीके से निपटान किया जाएगा?
nikib3ro

2
@ kape123 उत्तर "यह निर्भर करता है" है। जब तक Runnableविधि द्वारा लौटाई गई वस्तु कहीं भी मौजूद है, तब तक paramStrसंभवत: कचरा संग्रहण के लिए पात्र नहीं होंगे। यह संभव है कि यदि वस्तु मौजूद है, लेकिन फिर कभी नहीं चलाया जा सकता है, तो JIT (या यहां तक ​​कि javac) इसे दायरे से हटाने का फैसला कर सकता है, लेकिन हमें ऐसी आशाओं पर भरोसा नहीं करना चाहिए क्योंकि वे भविष्य में बदल सकते हैं।
corsiKa

"कोड साझा करने के लिए धन्यवाद - मुझे अच्छा लगता है जब लोग ऐसा करते हैं, बजाय सिर्फ बकवास के।" - क्या?
रोब ग्रांट

30
theView.post(new Runnable() {
    String str;
    @Override                            
    public void run() {
        par.Log(str);                              
    }
    public Runnable init(String pstr) {
        this.str=pstr;
        return(this);
    }
}.init(str));

इनटैट फंक्शन बनाएं जो ऑब्जेक्ट को खुद लौटाता है और इसके साथ मापदंडों को इनिशियलाइज़ करता है।


1
दुर्भाग्य से आप इसे एक वैरिएबल और कॉल
इनिट

11

मैं निम्न वर्ग का उपयोग करता हूं जो रननेबल इंटरफ़ेस को लागू करता है। इस वर्ग के साथ आप तर्कों के साथ आसानी से नए सूत्र बना सकते हैं

public abstract class RunnableArg implements Runnable {

    Object[] m_args;

    public RunnableArg() {
    }

    public void run(Object... args) {
        setArgs(args);
        run();
    }

    public void setArgs(Object... args) {
        m_args = args;
    }

    public int getArgCount() {
        return m_args == null ? 0 : m_args.length;
    }

    public Object[] getArgs() {
        return m_args;
    }
}

2
एक पैरामीटर के साथ एक रननेबल को चलाने के लिए आप इस अमूर्त वर्ग का उपयोग कैसे करेंगे?
EZDsIt

मैं पैरामीटर के साथ कंस्ट्रक्टर का उपयोग करना पसंद करता हूं, public RunnableArg(Object... args) { setArgs(args); } फिर स्थानीय वर्ग का वर्णन करता class ActionArg extends RunnableArg { public ActionArg(Object... arg) { super(arg); } @Override public void run() { /* getArgs() and process them */ } }Thread t = new Thread(new ActionArg( %param_object(s)% )); t.start();
हूं

10

आपके पास दो विकल्प हैं:

  1. एक नामित वर्ग को परिभाषित करें। नामित कक्षा के निर्माता को अपना पैरामीटर पास करें।

  2. अपना अनाम वर्ग अपने "पैरामीटर" के करीब रखें। इसे चिह्नित करना सुनिश्चित करें final



6

जावा 8 के बाद से, सबसे अच्छा जवाब उपयोग करना है Consumer<T>:

https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html

यह कार्यात्मक इंटरफेस में से एक है, जिसका अर्थ है कि आप इसे लंबोदर अभिव्यक्ति कह सकते हैं:

void doSomething(Consumer<String> something) {
    something.accept("hello!");
}

...

doSomething( (something) -> System.out.println(something) )

...

5

मैं पहले यह जानना चाहूंगा कि नए रननेबल () या रन () में पास होने के लिए एक तर्क की आवश्यकता के लिए आप यहां क्या हासिल करने की कोशिश कर रहे हैं। सामान्य तरीका यह होना चाहिए कि एक रनने योग्य वस्तु होनी चाहिए जो शुरू होने से पहले सदस्य चर सेट करके अपने थ्रेड्स को डेटा (str) पास करती है। रन () विधि तो इन सदस्य चर मानों का उपयोग करने के लिए someFunc () निष्पादित करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.