java - 内存不足错误: unable to create new native thread while using Executor

标签 java multithreading executorservice

我有一个执行器服务,其池大小为 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,因此只有一个后台线程在运行,其余线程都在队列中等待。在这种情况下,内存分配应该足够。我是否遗漏了什么,以及如何解决这个问题。

谢谢

最佳答案

只是为了为 future 的读者提供答案:

该解决方案的主要思想是仅初始化 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() 方法)时,这才有效。如果不是,则更改无效,因为容器将在每次请求时实例化资源的实例。

或者,您可以使用单例实例创建一个单独的类,然后调用它。但最合理的解决方法是将实例字段设为静态并将其设置在静态初始化 block 中:

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 类的 JavaDocs:http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/Application.html#getSingletons--

关于java - 内存不足错误: unable to create new native thread while using Executor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35936217/

相关文章:

java - 如何通过Gson解析单个字段

java - 如何在一个网格框中添加两个标签?

java - 扫描仪在使用 next() 或 nextFoo() 后跳过 nextLine()?

c++ - std::condition_variable 的 notify_all() 和 notify_one() 有什么区别?

java - 固定线程池执行器受到某些终止条件的限制

java - firestore collectionreference .get() 未执行

java - 同步的java线程错误的输出顺序

C++ std::map - 如果一个线程写入而另一个线程始终使用不同的键读取,则线程安全吗?

java - 在 Tomcat 中停止 ExecutorService 线程

java - 如何停止下一个线程在 ScheduledThreadPoolExecutor 中运行