2012-12-18 62 views
23

मैं जो ExecutorService इस्तेमाल किया समानांतरJboss जावा ईई कंटेनर और एक ExecutorService

ExecutorService es = Executors.newFixedThreadPool(10); 

में नौकरियों की संख्या में अब मैं एक EJB सेम के भीतर ही समाधान फिर से उपयोग करना चाहते हैं पर कार्रवाई करने के लिए एक स्वसंपूर्ण जावा अनुप्रयोग है, लेकिन मैं थ्रेडपूल को सही तरीके से प्रारंभ करने के बारे में अनिश्चित हूं, क्योंकि मैं सामान्य रूप से सभी थ्रेड संसाधनों को नियंत्रित करने के लिए जावा ईई कंटेनर छोड़ देता हूं। क्या मैं सिर्फ एक ही कोड का उपयोग कर सकता हूं या जेबॉस प्रबंधित थ्रेड पूल प्राप्त करने का कोई वैकल्पिक तरीका है?

उत्तर

25

अनिवार्य चेतावनी: जावा ईई ऐप सर्वर (यहां तक ​​कि टॉमकैट) में अपने स्वयं के धागे बनाना भी निराश है क्योंकि यह एक बड़ा प्रदर्शन मुद्दा हो सकता है और ज्यादातर मामलों में कंटेनर कार्यक्षमता, जैसे कि जेएनडीआई, काम करने से रोकती है। नए धागे नहीं जानते होंगे कि वे किस एप्लिकेशन से संबंधित हैं, थ्रेड संदर्भ क्लासलोडर सेट नहीं किया जाएगा और कई अन्य छिपे हुए मुद्दे नहीं होंगे।

सौभाग्य से जावा ईई सर्वर जावा ईई 6 @Asynchronous और इस चालाक डिजाइन पैटर्न के माध्यम से थ्रेड पूल का प्रबंधन करने का एक तरीका है। किसी भी जावा ईई 6 प्रमाणित सर्वर के लिए पोर्टेबल।

अपने आवेदन में यह ईजेबी बनाएं।

package org.superbiz; 

import javax.ejb.Asynchronous; 
import javax.ejb.EJB; 
import javax.ejb.Stateless; 
import java.util.concurrent.Callable; 
import java.util.concurrent.Executor; 

@Stateless(name="Executor") 
public class ExecutorBean implements Executor { 

    @Asynchronous 
    @Override 
    public void execute(Runnable command) { 
     command.run(); 
    } 
} 

तो फिर तुम सादे निर्भरता इंजेक्शन के माध्यम से अपने आवेदन में कहीं और इस सेम (चर्चा करते हुए घटक है अगर एक सर्वलेट, श्रोता, फ़िल्टर, अन्य EJB, JSF प्रबंधित सेम) देख सकते हैं।

@EJB 
private Executor executor; 

फिर सामान्य की तरह Executor का उपयोग करें।

घटक एक और जावा EE घटक नहीं है, तो आप के माध्यम से सेम देखने कर सकते हैं:

InitialContext initialContext = new InitialContext(); 
Executor executor = (Executor) initialContext.lookup("java:module/Executor"); 
+2

थोड़ा ओ/टी: यह एक बहुत अच्छा पैटर्न है (हम इसे बहुत उपयोग करते हैं), हालांकि यह तब कम हो जाता है जब आपके एल्गोरिदम को डेडलॉक्स को रोकने के लिए अलग थ्रेड-पूल की आवश्यकता होती है (इस बारे में ईजेबी स्पेक मुद्दे पर चर्चा भी देखें) –

+0

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

+0

ऐसा करने का सही तरीका प्रबंधित प्रबंधितकर्ता सेवा का उपयोग कर रहा है, मेरा उत्तर [नीचे] (http://stackoverflow.com/questions/13932083/jboss-java-ee-container-and- ए-एक्जिक्यूटर्स सर्विस/1 940460 9 # 1 9 40460 9) –

5

खैर ... डेविड का समाधान निम्नलिखित कारणों के लिए मेरे लिए काम नहीं किया:

  1. कंपाइलर उस java.util.concurrent की अनुमति नहीं दे रहा था ... जेबीएसएसएसएस क्षेत्र में किस तरह की समझ में आता है।
  2. इसके अलावा: सार्वजनिक स्थिति वर्ग ...? इस पढ़ें: Why are you not able to declare a class as static in Java?

यहाँ मैं क्या किया है:
मेरे स्थापना:
- JBoss के रूप में 7.1.1
- जावा 1.6
- RHEL
- Gradle और Arquillian साथ उदाहरण चल रहा है:

@Stateless 
public class ExecutorBean { 
    @Asynchronous 
    public void execute(Runnable command) { 
     command.run();  
    } 
} 

तब आपका ग्राहक इस तरह दिखता है:

@EJB ExecutorBean eb; 
@Test 
public void testExecutorBean() { 
    eb.execute(new YourCustomizedRunnableWhichDoesALotOfUsefulStuff()); 
    assertFalse(!true); 
} 

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

आशा है कि यह पोस्ट मदद करता है!

+0

मैंने अपने testmethod के लिए सबसे सुंदर समाधान तैयार किया है: बस मुख्य परीक्षण थ्रेड को कुछ समय तक सोएं ताकि ऐप सर्वर के प्रबंधन में मौजूद अन्य थ्रेडों को पूरा करने का समय हो। ठीक है ... इतना सुरुचिपूर्ण नहीं, लेकिन काम कर रहा है। – easyDaMan

+1

यांकेड 'स्थैतिक '- कोड I कॉपी किया गया एक स्थिर आंतरिक वर्ग था। पेस्ट कोड के रूप में हटाया गया था एक शीर्ष स्तर की कक्षा होने का इरादा था। –

26

अपने ईजेबी में ऐसा करने का सही तरीका ManagedExecutorService का उपयोग करना है, जो Concurrency Utils API (Java EE7) का हिस्सा है। आपको किसी भी निष्पादक सेवा का उपयोग नहीं करना चाहिए जो आपके एंटरप्राइज़ कोड में java.util.concurrent का हिस्सा है।

ManagedExecutorService का उपयोग करके आपका नया धागा कंटेनर द्वारा बनाया और प्रबंधित किया जाएगा।

निम्नलिखित उदाहरण मेरी साइट here से लिया गया है।

ManagedExecutorService का उपयोग करके एक नया धागा बनाने के लिए, पहले एक कार्य ऑब्जेक्ट बनाएं जो कॉलबल लागू करता है। कॉल() विधि के भीतर हम उस काम को परिभाषित करेंगे जिसे हम अलग थ्रेड में करना चाहते हैं।

public class ReportTask implements Callable<Report> { 

    Logger logger = Logger.getLogger(getClass().getSimpleName()); 

    public Report call() { 
     try { 
      Thread.sleep(3000); 
     catch (InterruptedException e) { 
      logger.log(Level.SEVERE, "Thread interrupted", e); 
     } 
     return new Report(); 
    } 
} 

फिर हम ManagedExecutorService की विधि प्रस्तुत(), हालांकि यह पारित करके कार्य को लागू करने की जरूरत है।

@Stateless 
public class ReportBean { 

    @Resource 
    private ManagedExecutorService executorService; 

    public void runReports() { 
     ReportTask reportTask = new ReportTask(); 
     Future<Report> future = executorService.submit(reportTask); 
    } 
} 
+5

ईई 7 में यह पसंदीदा तरीका है, लेकिन ईई 6 के बारे में क्या? – Vlad

+0

ऐसा करने का कोई सुरक्षित तरीका जावा ईई 6 नहीं है। मुझे लगता है कि यही कारण है कि यह जावा ईई 7 में शामिल होने के लिए वोट जीता। –

+0

धन्यवाद ... प्रबंधित निष्पादक का उपयोग निश्चित रूप से जाने का तरीका है। – Houston

2

EE7 करने से पहले, आप JSR 237

http://docs.oracle.com/javaee/1.4/api/javax/resource/spi/work/WorkManager.html

यह कल्पना वर्तमान में वापस ले लिया है से WorkManager उपयोग करने के लिए चाहते हो सकता है, अभी भी कुछ एप्लिकेशन सर्वर इसे लागू। मैं वेबस्पेयर 8.5 - IBM WorkManager में आईबीएम कार्यान्वयन का उपयोग करता हूं। यह पूरी तरह से प्रबंधित संसाधन है, प्रशासन कंसोल में उपलब्ध है। कृपया ध्यान दें कि यह ओरेकल के साथ इंटरफेस-अनुकूल नहीं है।

@Resource(lookup = "wm/default") 
WorkManager workManager; 

public void process() { 
    try { 
     ArrayList<WorkItem> workItems = new ArrayList<WorkItem>(); 
     for (int i = 0; i < 100; i++) { 
      // submit 100 jobs 
      workItems.add(workManager.startWork(new Work() { 
       @Override 
       public void run() { 
        try { 
         System.out.println(Thread.currentThread().getName() + " Running"); 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 

       @Override 
       public void release() { 
        System.out.println(Thread.currentThread().getName() + " Released"); 
       } 
      })); 
     } 
     // wait for all jobs to be done. 
     workManager.join(workItems, WorkManager.JOIN_AND, 100000); 
    } catch (WorkException e) { 
     e.printStackTrace(); 
    } 
} 

इसके अलावा, मैं Commonj Workmanager के बारे में पता कर रहा हूँ:

यहाँ आईबीएम संस्करण के लिए एक उदाहरण है।

0

यदि आप जेबॉस का उपयोग कर रहे हैं, तो आप org.jboss.seam.async.TreadPoolDispatcher का उपयोग कर सकते हैं।

ThreadPoolDispatcher पूरी तरह से प्रबंधित है।

अन्य उपयोगी प्रबंधित कक्षाओं के लिए, पैकेज देखें: org.jboss.seam.async।