2010-01-17 9 views
6

थ्रेड अक्सर दो तरीकों से डिजाइन किए जाते हैं (see java tutorials): या तो थ्रेड क्लास को विस्तारित करके या रननेबल क्लास को कार्यान्वित करके। किसी भी तरह से, आपको यह निर्दिष्ट करने की आवश्यकता है कि थ्रेड के अंदर क्या चलेंगे।एक वर्ग में एकाधिक धागे से निपटने के लिए कैसे?

मैंने एक ऑनलाइन संसाधन की ओर एक एडाप्टर बनाया है, जो विभिन्न प्रकार की जानकारी पुनर्प्राप्त करता है। इस श्रेणी में getInformationOfTypeA() और getInformationOfTypeB() प्राप्त करने के तरीके शामिल हैं। दोनों में ऑनलाइन संसाधनों से कनेक्ट करने के लिए कोड होता है, इसलिए दोनों को डेडलॉक्स से बचने के लिए थ्रेड किया जाना चाहिए।

सवाल यह है कि: मुझे इसे कैसे डिजाइन करना चाहिए? मैं इसे नीचे की तरह कर सकते हैं, लेकिन तब मैं केवल एक विधि को लागू कर सकते हैं:

public class OnlineResourceAdapter implements Runnable { 

    public void run() { 
     //get stuff from resource 
     getInformationOfTypeA(); 
    } 

    public static void main(String args[]) { 
     (new Thread(new OnlineResourceAdapter())).start(); 
    } 

    public void getInformationOfTypeA(){ 
     //get information of type A 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 

} 

एक और तरीका है प्रत्येक विधि के लिए अलग वर्ग बनाने के द्वारा होगा, लेकिन है कि मेरे पास अप्राकृतिक लगता है।

Btw: मैं जे 2 एमई में अपने आवेदन के विकास कर रहा हूँ

अद्यतन:

अपनी प्रतिक्रियाओं के लिए धन्यवाद मुझे लगता है कि यह सबसे अधिक suiting तरीके के रूप में निम्नलिखित की तरह कुछ का उपयोग करने के लिए है:

आप इस बारे में क्या सोचते हैं:

public class OnlineResourceAdapter{ 
    public void getInformationOfTypeA(){ 
     Thread t = new Thread(new Runnable() {   
      public void run() { 
       //do stuff here 
      } 
     }); 
     t.start(); 
    } 

    public void getInformationOfTypeB(){ 
     Thread t = new Thread(new Runnable() {   
      public void run() { 
       //do stuff here 
      } 
     }); 
     t.start(); 
    } 
} 

वा क्या आप इस बारे में सोचते हैं?

उत्तर

1

प्रत्येक वर्ग के लिए रननेबल पर आधारित एक अज्ञात वर्ग बनाएं। यह आपको चलाने की अनुमति देगा जो आपको रन() विधि के अंदर करने की ज़रूरत है।

6

यह मुझे लगता है कि वास्तव में आपके पास दो अलग-अलग कक्षाएं होनी चाहिए: InformationOfTypeAFetcher और InformationOfTypeBFetcher, जिनमें से प्रत्येक को Runnable लागू करना चाहिए। उनमें से प्रत्येक को आपके OnlineResourceAdapter (या कुछ समान) के उदाहरण का संदर्भ हो सकता है लेकिन यदि वे अलग-अलग चीजें कर रहे हैं, तो वे अलग-अलग कक्षाएं होनी चाहिए।

1

मुझे नहीं लगता कि आप एकाधिक वर्ग बनाने के विचार को क्यों पसंद नहीं करते हैं, क्योंकि जावा उच्च-आदेश कार्यों का समर्थन नहीं करता है और आपके कोड का परिवर्तनीय हिस्सा एल्गोरिदम है।

लेकिन अगर आप OnlineResourceAdapter की एक एकल कार्यान्वयन चाहता था आप रणनीति पैटर्न का उपयोग करें और कुछ इस तरह कर सकता है:

public interface InformationGetter { 
    public void getInformation(); 
} 

public class OnlineResourceAdapter implements Runnable { 
    private final InformationGetter informationGetter; 

    public OnlineResourceAdapter(InformationGetter i) { 
    this.informationGetter = i; 
    } 

    public void run() { 
     //get stuff from resource 
     i.getInformation(); 
    } 
} 

और फिर बेशक आप InformationGetter के रूप में कई कार्यान्वयन के रूप में आप की जरूरत पैदा करेगा।

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

+0

डैनबेन मेरी राय का प्रतीक है। रणनीति पैटर्न एक चीज है जिसे आप देखना चाहते हैं। इस मामले में अलग-अलग कक्षाएं मेरे लिए एक साफ तरीके की तरह दिखती हैं – Aadith

1

कई लोगों ने पहले से ही कई वर्गों का उपयोग करके इसे कैसे किया जाए इसके अच्छे तरीके सुझाए हैं।

public class OnlineResourceAdapter implements Runnable 
{ 
    private string resourceType; 

    public OnlineResourceAdapter(string resourceType) 
    { 
     this.resourceType = resourceType; 
    } 

    public void run() { 
     if (resourceType.equals("A") { 
      getInformationOfTypeA(); 
     } else { 
      // etc.. 
     } 
    } 

    public void getInformationOfTypeA(){ 
     //get information of type A 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 
} 

उपयोग::

(new Thread(new OnlineResourceAdapter("A"))).start(); 
+0

जब तक आप वास्तव में नहीं, वास्तव में ऐसा नहीं करना है। जितना अधिक आप स्थिर टाइपिंग के तहत रख सकते हैं उतना ही बेहतर। दूसरे शब्दों में, दो अलग-अलग वर्ग हैं। –

+0

दूसरी तरफ, यदि आपके पास संभावित रूप से हजारों प्रकार की जानकारी पुनर्प्राप्त करने के लिए है, या प्राप्त करने के लिए जानकारी का प्रकार एक पैरामीटर है जो उपयोगकर्ता प्रवेश करता है, तो यह विधि एक प्रकार के कंसक्टर पैरामीटर के रूप में टाइप करने के लिए बहुत अधिक समझदारी करेगी प्रत्येक प्रकार के लिए एक नई कक्षा बनाना। पोस्टर की ज़रूरतों के बारे में और जानने के बिना, यह कहना मुश्किल है कि सबसे अच्छा समाधान क्या है। –

-1

उपयोग जब से तुम एक तरह से जो कई वर्गों की आवश्यकता नहीं है पसंद करते हैं करने लगते हैं, तो आप भी निर्माता का उपयोग कर जानकारी के बारे में जो संसाधन लाने के लिए देने के लिए विचार करना चाह सकते Callable के अज्ञात वर्ग (जो Runnable के विपरीत, मान वापस कर सकते हैं) और उन्हें Executor का उपयोग करके निष्पादित करें। यदि जानकारी को पुनर्प्राप्त करने के लिए तर्क ए और सूचना बी बहुत समान है, तो आप निश्चित रूप से उसमें दोबारा प्रतिक्रिया कर सकते हैं और एकल का उपयोग कर सकते हैं, कॉलबेल के आंतरिक वर्ग को पैरामीटर कर सकते हैं।

मुझे यकीन नहीं है कि कॉल करने योग्य और निष्पादक हालांकि जे 2 एमई स्पेक का हिस्सा हैं। मानक जावा में, मैं Proxy दृष्टिकोण के लिए वैसे भी जाऊंगा और बाह्य संसाधन को इंटरफेस के रूप में समाहित करता हूं।

public class AsyncMethodsTest { 

    public class OnlineResourceAdapter { 

     private final ExecutorService executor = Executors.newFixedThreadPool(2); 

     public String getInformationOfTypeA() throws InterruptedException, ExecutionException, 
       TimeoutException { 
      Callable<String> callable = new Callable<String>() { 
       @Override 
       public String call() throws Exception { 
        // Connect to external resource 
        Thread.sleep(500); 
        return "A"; 
       } 

      }; 
      Future<String> submit = executor.submit(callable); 
      return submit.get(1000, TimeUnit.MILLISECONDS); 
     } 

     public String getInformationOfTypeB() throws InterruptedException, ExecutionException, 
       TimeoutException { 
      Callable<String> callable = new Callable<String>() { 
       @Override 
       public String call() throws Exception { 
        // Connect to external resource 
        Thread.sleep(1500); 
        return "B"; 
       } 

      }; 
      Future<String> submit = executor.submit(callable); 
      return submit.get(1000, TimeUnit.MILLISECONDS); 
     } 

    } 

    @Test 
    public void testMethodCalls() throws Exception { 
     OnlineResourceAdapter adapter = new OnlineResourceAdapter(); 
     assertNotNull(adapter.getInformationOfTypeA()); 
     assertNotNull(adapter.getInformationOfTypeB()); 
    } 
} 
+1

दुर्भाग्य से, जावा ME में कोई 'java.util.concurrent' नहीं है। – BalusC

4

दो अज्ञात आंतरिक वर्ग, जैसे थोरबोजर्न रावण एंडर्सन ने उपरोक्त सुझाव दिया, काम करता है। यहाँ एक कोड उदाहरण है:

public class OnlineResourceAdapter { 

    public final Runnable typeA; 
    public final Runnable typeB; 

    public OnlineResourceAdapter() { 
     typeA = new Runnable() { 
      public void run() { 
       OnlineResourceAdapter.this.getInformationOfTypeA(); 
      } 
     }; 
     typeB = new Runnable() { 
      public void run() { 
       OnlineResourceAdapter.this.getInformationOfTypeB(); 
       // one can use a non-final typed variable 
       // to store, which then<1> 
      } 
     }; 
    } 

    public static void main(String args[]) { 
     OnlineResourceAdapter x = new OnlineResourceAdapter(); 
     new Thread(x.typeA).start(); // start A 
     new Thread(x.typeB).start(); // start B 
     // <1>can be accessed here. 
    } 

    public void getInformationOfTypeA(){ 
     // get information of type A 
     // return the data or directly store in OnlineResourceAdapter. 
    } 

    public void getInformationOfTypeB(){ 
     //get information of type B 
    } 

} 

संपादित करें: हाँ, आप प्रस्तावित कर रहे हैं जिस तरह से एक अच्छा तरीका है। आप विधियों को स्थिर भी बना सकते हैं। आप "OnlineResourceAdapter.this" का उपयोग कर सकते हैं। परिणामों को स्टोर करने के लिए अन्य चरों तक पहुंचने के लिए।

+0

अनाम कक्षाओं के मेरे संस्करण के बारे में आप क्या सोचते हैं? – hsmit

+0

यह काम करना चाहिए। मुझे यकीन नहीं है कि इस कक्षा को थ्रेडिंग को संभालने देना अच्छा है: क्योंकि आप इसे अन्य कक्षाओं से नियंत्रित नहीं कर सकते हैं। एक त्वरित समाधान के रूप में, यह काम करेगा, लेकिन मैं इसे दीर्घकालिक समाधान के रूप में सलाह नहीं दूंगा। शायद "getInformationOfTypeARunnable()" विधियों द्वारा रननेबल इंटरफ़ेस का पर्दाफाश करें, जो तब केवल एक रननेबल लौटाता है। साथ ही, किसी अन्य थ्रेड से उन्हें एक्सेस करने का प्रयास करते समय चर ("अस्थिर" कीवर्ड) के सिंक्रनाइज़ेशन को न भूलें। – Pindatjuh

संबंधित मुद्दे