2013-05-28 5 views
5

Ich habe ein seltsames Problem. Ich versuche das Producer/Consumer Model zu verwenden. Bitte schlage vor, dass ich hier etwas falsch gemacht habe. Wenn ich den ExecutorService mit festen Thread von 4 verwende, bekomme ich keine Ausnahme und Programm läuft, aber wenn ich ThreadPoolExecutor verwenden, gibt es mir die Ausnahme. Kann nicht herausfinden, was der Fehler ist! Bitte beraten!Java ExecutorService und ThreadPoolExecutor

Code von 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); 
} 

Code of 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); 
      } 

Ausnahme, wenn ich laufen ThreadPoolExecutor:

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 Eigenschaften Datei

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-Code

@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 setzen Code in LogFileWriter

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

Sieht aus wie Sie versuchen, auf null Datei zu protokollieren. Welche Linie ist 202 in BillingConsu.java? – BobTheBuilder

+0

Wie @whoAmI sagt. Dies scheint ein log4j-Konfigurationsproblem zu sein, kein Thread-Pool-bezogenes Problem ... – fge

+0

@whoAmI Es ist resp = neu StsSmsConnection(). DoRequest (sms); Aber es ist dieselbe Datei, die von ExecutorService ausgeführt wird !! und keine Ausnahme –

Antwort

8

Wie ich erwartet Sie wegen faden Ort versagen. Die Linie ist hier der Rückkehr an Sicherheit grenzender Wahrscheinlichkeit null

MDC.get(ORIG_LOG_FILE_NAME) 

Wann/Wo sehen Sie MDC.put? Das Problem hier ist, dass MDC eine Thread-lokale Karte verwendet. Wenn Sie Callable ausführen, versucht es einen separaten Thread einzuloggen. Dieser Thread wurde nicht mit MDC registriert und get gibt null zurück.

Ihre Anwendung Stellen ähnelt

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

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

Nun, wenn Sie in Executor-Thread-1..N sind, wird es

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

Es wird null zurück

tun, wenn Sie laufen außerhalb der Executor Service Threads funktioniert es

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

Ihre nächste Frage ist also: "Warum scheitert es nicht mit einem ExecutorService?" Es ist wahrscheinlich oder würde und wird möglicherweise nicht gemeldet. Ich bemerke, dass Ihre Reihenfolge der Übermittlung an den ExecutorService anders als TPE ist. Vielleicht möchten Sie versuchen, sie zu vergleichen und zu sehen, ob Sie die gleiche Ausgabe erhalten.

Edit: möchten dies als fix versuchen

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

Dies geschah, als ich den gesamten Log-Nachrichtenausgangscode auskommentierte !! –

+0

Ich habe den Code für MDC.put-Code hinzugefügt, der in LogFileWriter ist –

+0

Sehen Sie, ob Sie 'MDC.put (ORIG_LOG_FILE_NAME, Dateiname);' von der 'BillingConsu.call' Methode vor' doStsBilling' aufrufen können. Wahrscheinlich nicht die gewünschte Lösung. Ich werde vielleicht eine bessere Lösung posten, wenn das funktioniert. –