2013-05-28 16 views
5

Mam dziwny problem. Próbuję użyć Producer/Consumer Model, Proszę zasugerować, jeśli zrobiłem coś złego tutaj. Kiedy używam ExecutorService z ustalonym wątkiem 4, nigdy nie otrzymuję żadnego wyjątku i program działa, ALE gdy używam ThreadPoolExecutor, to daje mi wyjątek. Nie mogę się dowiedzieć, jaki jest błąd! Proszę doradź!Java ExecutorService and ThreadPoolExecutor

kod ExecutorService:

ArrayBlockingQueue<BillableList> list =new ArrayBlockingQueue<BillableList>(2); 
ThreadFactory threadFactory = Executors.defaultThreadFactory(); 
ExecutorService threadPool = Executors.newFixedThreadPool(4, threadFactory); 

    threadPool.execute(new BillingConsu(network,"consumer->"+Thread.currentThread(), list)); 
    threadPool.execute(new BillingConsu(network,"consumer->"+Thread.currentThread(), list)); 
    threadPool.execute(new BillingConsu(network,"consumer->"+Thread.currentThread(), list)); 

Future producerStatus = threadPool.submit(new BillProdu(this.network,"Producer", list)); 
producerStatus.get(); 
threadPool.shutdown(); 

while (!threadPool.isTerminated()) { 
threadPool.shutdown(); 
threadPool.awaitTermination(10, TimeUnit.SECONDS); 
} 

Kodeks ThreadPoolExecutor:

ArrayBlockingQueue<BillableList> list =new ArrayBlockingQueue<BillableList>(4); 
BlockingQueue<Runnable> worksQueue = new ArrayBlockingQueue<Runnable>(100); 
RejectedExecutionHandler executionHandler = new MyRejectedExecutionHandelerImpl(); 
ThreadFactory threadFactory = Executors.defaultThreadFactory(); 
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5,5, 10, 
TimeUnit.SECONDS, worksQueue,threadFactory, executionHandler); 
Future producerStatus = threadPool.submit(new BillProdu(this.network,"Producer", list)); 
producerStatus.get(); 

    threadPool.execute(new BillingConsu(network,"consumer 1", list)); 
    threadPool.execute(new BillingConsu(network,"consumer 2", list)); 
    threadPool.execute(new BillingConsu(network,"consumer 3", list)); 
    threadPool.execute(new BillingConsu(network,"consumer 4", list)); 
    threadPool.shutdown(); 

      while (!threadPool.isTerminated()) { 
       threadPool.shutdown(); 
       threadPool.awaitTermination(10, TimeUnit.SECONDS); 
      } 

Wyjątek kiedy biegnę ThreadPoolExecutor: Właściwości

Exception in thread "pool-1-thread-2" java.lang.ExceptionInInitializerError 
    at org.apache.axis.utils.Messages.<clinit>(Messages.java:36) 
    at org.apache.axis.configuration.EngineConfigurationFactoryFinder$1.run (EngineConfigurationFactoryFinder.java:141) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at org.apache.axis.configuration.EngineConfigurationFactoryFinder.newFactory (EngineConfigurationFactoryFinder.java:113) 
    at org.apache.axis.configuration.EngineConfigurationFactoryFinder.newFactory (EngineConfigurationFactoryFinder.java:160) 
    at org.apache.axis.client.Service.getEngineConfiguration(Service.java:813) 
    at org.apache.axis.client.Service.getAxisClient(Service.java:104) 
    at org.apache.axis.client.Service.<init>(Service.java:113) 
    at org.tempuri.OnlineBillingLocator.<init>(OnlineBillingLocator.java:28) 
    at com.mixem.sdc.sms.StsSmsConnection.<init>(StsSmsConnection.java:40) 
    at BillingConsu.doStsBilling(BillingConsu.java:202) 
    at BillingConsu.run(BillingConsu.java:60) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    at java.lang.Thread.run(Thread.java:619) 
Caused by: java.lang.NullPointerException 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:172) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:102) 
    at org.apache.log4j.FileAppender.setFile(FileAppender.java:290) 
    at LogFileWriter.append(LogFileWriter.java:45) 
    at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251) 
    at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders (AppenderAttachableImpl.java:66) 
    at org.apache.log4j.Category.callAppenders(Category.java:206) 
    at org.apache.log4j.Category.forcedLog(Category.java:391) 
    at org.apache.log4j.Category.log(Category.java:856) 
    at org.apache.commons.logging.impl.Log4JLogger.debug(Log4JLogger.java:177) 
    at org.apache.axis.i18n.ProjectResourceBundle.getBundle(ProjectResourceBundle.java:264) 
    at org.apache.axis.i18n.MessagesConstants.<clinit>(MessagesConstants.java:32) 

LOG4J File

log4j.rootLogger = DEBUG, fileout 
log4j.appender.fileout = LogFileWriter 
log4j.appender.fileout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c - %m%n 
log4j.appender.fileout.layout = org.apache.log4j.PatternLayout 
log4j.appender.fileout.File = /logs/billinglogs.log 

Kod LogFileWriter Dołącz

@Override 
public void append(LoggingEvent event) { 
try { 
setFile(appendLevelToFileName((String) MDC.get(ORIG_LOG_FILE_NAME), 
event.getLevel().toString()), fileAppend, bufferedIO,bufferSize); 
} catch (IOException ie) { 
errorHandler.error("Error occured while setting file for the log level "+ event.getLevel(), ie, 
ErrorCode.FILE_OPEN_FAILURE); 
    } 
super.append(event); 
} 

MDC umieścić kod wewnątrz LogFileWriter

@Override 
public void activateOptions() { 
MDC.put(ORIG_LOG_FILE_NAME, fileName); 
super.activateOptions(); 
} 
+2

wygląda starasz się zalogować null pliku. Jaka jest linia 202 w BillingConsu.java? – BobTheBuilder

+0

Jak mówi @whoAmI. Wydaje się, że jest to problem z konfiguracją log4j, a nie problem związany z pulą wątków ... – fge

+0

@whoAmI To jest resp = new StsSmsConnection(). DoRequest (sms); Ale to ten sam plik, który jest uruchamiany przez ExecutorService !! i bez wyjątku –

Odpowiedz

8

Jak oczekiwano jesteś z powodu braku nitki miejscowości. Linia jest tu niemal na pewno powrocie zerowy

MDC.get(ORIG_LOG_FILE_NAME) 

Kiedy/gdzie czego MDC.put? Problem polega na tym, że MDC używa lokalnej mapy wątku. Tak więc, gdy uruchomisz program Callable, spróbujesz zalogować się w osobnym wątku. Ten wątek nie został zarejestrowany w MDC, a get zwróci wartość null.

Wyobraźmy sobie aplikację wygląda podobnie do

Main-Thread 
    MDC.put -> sets thread-local-map(Main-Thread, ORIG_LOG_FILE_NAME) 

Executor-Thread-1 
Executor-Thread-2 
Executor-Thread-N 

Teraz, gdy jesteś w Executor thread 1..n to zrobi

Executor-Thread-N 
    MDC.get(Executor-Thread-N, ORIG_LOG_FILE_NAME) 

Powróci zerowej

Jeśli uruchamianie poza wątkami usługi Executor działa

Twoje następne pytanie brzmi: "Dlaczego usługa ExecutorService nie zawodzi?" Prawdopodobnie jest lub będzie i może nie zostać zgłoszone. Zauważam, że kolejność składania do ExecutorService jest inna niż TPE. Może chcesz spróbować je dopasować i sprawdzić, czy otrzymujesz te same wyniki.

Edit: Może chcesz spróbować to jako fix

ThreadFactory threadFactory = new ThreadFactory() { 
    public Thread newThread(final Runnable r) { 
     return Executors.defaultThreadFactory().newThread(new Runnable(){ 
      public void run() { 
       MDC.put(ORIG_LOG_FILE_NAME, fileName); 
       r.run(); 
      } 
     }); 
    } 
}; 
+0

Stało się to, gdy skomentowałem cały kod wyjściowy logu !! –

+0

Dodałem kod dla kodu MDC.put, który znajduje się w LogFileWriter –

+0

Zobacz, czy możesz wywołać 'MDC.put (ORIG_LOG_FILE_NAME, fileName);' z metody 'BillingConsu.call' przed' doStsBilling'. Prawdopodobnie nie taka poprawka, jakiej pragniesz. Wezmę może lepsze rozwiązanie, jeśli to zadziała. –

Powiązane problemy