Reputation: 109
Here is the situation: I have to use Xfire to exchange data with a server.The server can not handle to much concurrency.50 is the limit.So I plan to use ExecutorService to limit the amount of concurrent threads.Then Q&A find the usage of memory is nearly 100% when it has 50 concurrency after the program is running 20 mins.
Here is my code:
public class 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;
}
}
public class MyCallable implements Callable{
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;
}
}
Can anybody explain why and how to solve this problem?
or is there someone knows how to limit the amount of concurrent threads?
Upvotes: 0
Views: 1672
Reputation: 719346
There are two possibilities:
It is caused by having too many threads in the thread pool. Each thread could have a 2Mb stack, and active threads will most likely have objects on their respective stacks.
It is caused by memory leaks that are exacerbated by having lots of threads active. (One possibility is a memory leak due to not using thread-local variables properly.)
You'll need to investigate with a memory profiler.
how to limit the amount of concurrent threads?
Simple. Reduce the executor's thread pool size.
Upvotes: 1