我有一个执行者服务,其池大小为1.
代码:
@POST
@Path("insertOrUpdate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response insertOrUpdate(final String user) {
try {
new MYSQLProvider().insertOrUpdate(user);
resulTObj.put("success", true);
resulTObj.put("msg", "");
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute( new Runnable() {
@Override
public void run() {
//fetch list of all the user ids here and fire a multicast
log4j.info("Executor called");
Map<String, String> m = new HashMap<String, String>();
m.put("TAG", "MOVEMENT");
m.put("user", user);
GCMServerJava.sendMsgToAll(m);
}
});
} catch (SQLException | JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
resulTObj.put("success", false);
resulTObj.put("msg", e.getMessage());
}
return Response.status(200).entity(resulTObj.toString()).build();
}
我在服务器上运行几天后收到OutOfMemory错误。为什么会这样?在任何地方都提到Java堆大小越来越少,我们需要增加它。我的理解是,由于我的线程池大小只有1,所以只有一个后台线程在运行,其余的都在队列中等待。在这种情况下,内存分配应该足够了。我错过了什么,还有如何解决这个问题。
感谢
答案 0 :(得分:2)
为未来的读者提供答案:
该解决方案的主要思想是仅初始化ExecutorService实例一次,并在每个请求上重复使用它(参见上面的注释)。
如果您使用单例资源或以某种方式手动实例化它们,最好将执行程序服务保留为实例字段,并在操作方法中引用它:
public class MySqlResource{
private final ExecutorService executor;
public MySqlResource() {
this.executor = Executors.newFixedThreadPool(1);
}
@POST
@Path("insertOrUpdate")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response insertOrUpdate(final String user) {
try {
new MYSQLProvider().insertOrUpdate(user);
resulTObj.put("success", true);
resulTObj.put("msg", "");
executor.execute( new Runnable() {
@Override
public void run() {
//...run() code goes here
}
});
} catch (SQLException | JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
resulTObj.put("success", false);
resulTObj.put("msg", e.getMessage());
}
return Response.status(200).entity(resulTObj.toString()).build();
}
}
注意:如上所述,只有将上述资源作为单例提交(使用应用程序类的getSingletons()
方法),才能使用此方法。如果没有,则更改无效,因为容器将在每个请求上实例化资源实例。
或者,您可以创建一个单独的类,使用单例实例,然后调用它。但最合理的解决方法是使实例字段静态并将其设置在静态初始化块中:
public class MySqlResource {
//Note that the field is now static
private static final ExecutorService executor;
static {
MySqlResource.executor = Executors.newFixedThreadPool(1);
}
//.....
//Then the method can invoke it just as in the previous solution:
public Response insertOrUpdate(final String user) {
//...
MySqlResource.executor.execute( new Runnable() {
@Override
public void run() {
//...run() code goes here
}
});
//...
}
}
如果您遇到静态字段问题,那么您可以创建一个单独的单例类实例来保存执行程序服务对象。
有关单例资源的信息,请在此处检查Application类的JavaDoc:http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Application.html#getSingletons--
答案 1 :(得分:0)
ExecutorService池应该是静态的(最终是最终的)。