2013-05-28 14 views
5

Ho riscontrato uno strano problema. Sto cercando di utilizzare il modello Producer/Consumer, Si prega di suggerire se ho fatto qualcosa di sbagliato qui. Quando utilizzo ExecutorService con thread fissi di 4, non ottengo mai eccezioni e il programma viene eseguito MA quando utilizzo ThreadPoolExecutor, mi dà l'eccezione. Non riesci a scoprire qual è l'errore! Si prega di avvisare! CodiceJava ExecutorService e ThreadPoolExecutor

di 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); 
} 

Codice di 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); 
      } 

Eccezione quando corro ThreadPoolExecutor: proprietà

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 

LogFileWriter Append Codice

@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 messo codice all'interno LogFileWriter

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

Sembra che si sta cercando di accedere a null file. Quale riga è 202 in BillingConsu.java? – BobTheBuilder

+0

Come dice @whoAmI. Questo sembra essere un problema di configurazione di log4j, non un problema relativo al pool di thread ... – fge

+0

@whoAmI È risp = new StsSmsConnection(). DoRequest (sms); Ma è lo stesso file che viene eseguito da ExecutorService !! e nessuna eccezione –

risposta

8

Come mi aspettavo non si riescono a causa del filo-località. La linea qui è quasi certamente tornando nulla

MDC.get(ORIG_LOG_FILE_NAME) 

quando/dove ti MDC.put? Il problema qui è che MDC utilizza una mappa locale del thread. Quindi, quando esegui il Callable, tenterà di accedere a un thread separato. Quella discussione non è stata registrata con MDC e get restituirà null.

Immaginate la vostra applicazione è simile a

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

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

Ora, quando si è in Executor-Thread-1..N si farà

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

Si ritorna null

Se Esegui all'esterno dei thread del servizio Executor funziona

Main-Thread 
    MDC.get(Main-Thread, ORIG_LOG_FILE_NAME) // will be non-null 

Quindi la tua prossima domanda è: "Perché non sta fallendo con un ExecutorService?" Probabilmente è o sarebbe e potrebbe non essere segnalato. Ho notato che il tuo ordine di invio a ExecutorService è diverso da TPE. Potresti provare ad abbinarli e vedere se ottieni lo stesso risultato.

Edit: consiglia di provare questo come una correzione

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

Questo è accaduto quando ho commentato tutto il codice di uscita del messaggio Log !! –

+0

Ho aggiunto il codice per il codice MDC.put che si trova in LogFileWriter –

+0

Vedere se è possibile richiamare 'MDC.put (ORIG_LOG_FILE_NAME, fileName);' dal metodo 'BillingConsu.call' prima di' doStsBilling'. Probabilmente non è la soluzione che desideri. Pubblicherò forse una soluzione migliore se funziona. –

Problemi correlati