2013-07-14 24 views
0

這裏的情況: 我必須使用Xfire與服務器交換數據。服務器不能處理太多的併發.50是限制。因此,我打算使用ExecutorService來限制金額並行線程數。然後Q &當程序運行20分鐘後,如果有50個併發,則查找內存使用率接近100%。ExecutorService需要太多的內存

這裏是我的代碼:

公共類CompletionServiceImpl {

private static Logger logger = Logger.getLogger("BackgroundLog"); 

private int threadNum; 

private ExecutorService executor = null; 

private CompletionService<Integer> sc = null; 

private static CompletionServiceImpl completionServiceImpl = null; 

private CompletionServiceImpl(){ 
    this.threadNum = getThreadNum(); 
    this.executor = Executors.newFixedThreadPool(threadNum); 
    this.sc = new ExecutorCompletionService<Integer>(executor); 
} 

/*** 
* get the size of thread pool 
***/ 
private int getThreadNum(){ 

    int threadNum = 5; 
    Properties props = new Properties(); 
    try { 
     props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("tlWeixinconfig.properties")); 
     threadNum = Integer.parseInt(props.getProperty("THREAD_NUM")); 
    } catch (IOException e) { 
     logger.error(e.getMessage(), e); 
    } 
    return threadNum; 
} 


public static CompletionServiceImpl getInstance(){ 
    if(completionServiceImpl == null){ 
     synchronized(CompletionServiceImpl.class){ 
      if(completionServiceImpl == null){ 
       logger.info("thread pool is initialized."); 
       completionServiceImpl = new CompletionServiceImpl(); 
      } 
     } 
    } 
    return completionServiceImpl; 
} 

public ExecutorService getExecutor() { 
    return executor; 
} 

public CompletionService<Integer> getSc() { 
    return sc; 
} 

}


公共類MyCallable實現可調用{

private static Logger logger = Logger.getLogger("BackgroundLog"); 

private String id; 

private String usr; 

private String type; 

private String expireDate; 

private String billingURL; 

private int timeout; 

private int result; 

public MyCallable(String id, String usr,String type, String expireDate, String billingURL,int timeout,int result){ 
    super(); 
    this.id = id; 
    this.usr = usr; 
    this.type = type; 
    this.expireDate = expireDate; 
    this.billingURL = billingURL; 
    this.timeout = timeout; 
    this.result = result; 
} 

private int newinsertdrawcn(int result)throws Throwable { 
     try { 
      URL url = new URL(billingURL); 
      HttpURLConnection httpConnection = (HttpURLConnection)url.openConnection(); 
      httpConnection.setConnectTimeout(timeout); 

      httpConnection.connect(); 
      Client client = new Client(httpConnection.getInputStream(), null); 
      client.setProperty(CommonsHttpMessageSender.HTTP_TIMEOUT, String.valueOf(timeout)); 
      client.setProperty(CommonsHttpMessageSender.DISABLE_KEEP_ALIVE, "true"); 
      client.setProperty(CommonsHttpMessageSender.DISABLE_EXPECT_CONTINUE, "true"); 

      Object[] results = client.invoke("drawcn", new Object[] {id, usr, type, expireDate }); 
      if (results.length > 0) { 
       result = Integer.parseInt(results[0].toString()); 
      } 
     } catch (Throwable t) { 
      throw t; 
     } 
     return result; 
    } 

@Override 
public Integer call(){ 
    try{ 
     result = newinsertdrawcn(result); 
    }catch(Throwable t){ 
     logger.error(t.getMessage(),t); 
    } 
    return result; 
} 

}

任何人都可以解釋爲什麼以及如何解決這個問題?

還是有人知道如何限制併發線程的數量?

+0

什麼是您的系統配置? 50對於普通開發者機器來說很重要。 – kosa

+0

我得到8G內存,系統是RHEL 4.我們發現命令java需要大約1500M +內存。 – Allerson

+1

你有多少核心?如果線程數量比核心數量高很多,那就太過分了。 – kosa

回答

1

有兩種可能性:

  • 它是由線程池中有線程太多造成的。每個線程可以有2Mb堆棧,並且活動線程很可能在其各自的堆棧上有對象。

  • 這是由於大量線程活動而加劇的內存泄漏引起的。 (一種可能性是由於未正確使用線程局部變量導致的內存泄漏。)

您需要使用內存分析器進行調查。


如何限制併發線程的數量?

簡單。減少執行程序的線程池大小。