【问题标题】:Threads are not closing automatically线程不会自动关闭
【发布时间】:2020-07-19 06:01:18
【问题描述】:

即使从 run() 返回后,启动的线程看起来也没有关闭。在 Netbeans 的左侧面板中,它显示了许多“pool-xx-thread-1-running”,并且每次执行线程时都会增加。以下是我的代码:

// 监听操作 client.subscribe("/location/#", new IMqttMessageListener() { public void messageArrived(最终字符串主题,最终 MqttMessage 消息)抛出异常 { 最终字符串负载 = 新字符串(message.getPayload());

            System.out.println("Received operation " + payload);
            if (payload.startsWith("{\"location\":")) {
                // execute the operation in another thread to allow the MQTT client to
                // finish processing this message and acknowledge receipt to the server
                Executors.newSingleThreadScheduledExecutor().execute(new Runnable() {
                    public void run() {
                        if(payload.equals("")) return;

                        try {
                            JsonObject jsonObject = new Gson().fromJson(payload, JsonObject.class);
                            String fixTime="", vehicleid="", deviceTime="", lat="", lon="", speed="",alt="", accuracy="", bearing="";
                            try{
                                String locationStr=jsonObject.get("location").toString();
                                locationStr=locationStr.substring(1, locationStr.length()-1).trim();
                                locationStr=locationStr.replace("\\", "");
                                JsonObject locationJson = new Gson().fromJson(locationStr, JsonObject.class);
                                try{
                                    long millis = Long.parseLong(locationJson.get("mTime").toString());
                                    Calendar cal = Calendar.getInstance();
                                    cal.setTimeInMillis(millis);
                                    fixTime = df.format(cal.getTime());
                                }catch(Exception ex){

                                }

                                lat=locationJson.get("mLatitude").toString();
                                lon=locationJson.get("mLongitude").toString();
                                alt=locationJson.get("mAltitude").toString();
                                speed=locationJson.get("mSpeed").toString();
                                accuracy=locationJson.get("mAccuracy").toString();
                                bearing=locationJson.get("mBearing").toString();
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }

                            try{
                                String entityStr = jsonObject.get("entity").toString();
                                JsonObject entityJson = new Gson().fromJson(entityStr, JsonObject.class);
                                vehicleid = entityJson.get("id").toString();
                                vehicleid = vehicleid.replace("\"", "");
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }

                            try{
                                String headerStr=jsonObject.get("header").toString();
                                JsonObject headerJson = new Gson().fromJson(headerStr, JsonObject.class);
                                String deviceTimeMsStr = headerJson.get("timestamp").toString();
                                long msTime = Long.parseLong(deviceTimeMsStr);
                                Calendar cal = Calendar.getInstance();
                                cal.setTimeInMillis(msTime);
                                deviceTime = df.format(cal.getTime());
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }

                            Connection conn = null;
                            Statement stmt = null;
                            try{
                                String SQL = "INSERT INTO positions(protocol, deviceid, devicetime, fixtime, valid, latitude, longitude, altitude, speed, course, address, attributes, accuracy, network)";
                                SQL += " VALUES('osmand',(SELECT id FROM devices WHERE uniqueid = '" + vehicleid + "'),'" + deviceTime + "','" + fixTime + "',1," + lat + "," + lon + "," + alt + "," + speed + "," + bearing + ",'',''," + accuracy + ",'')";

                                Class.forName("com.mysql.jdbc.Driver");
                                conn =DriverManager.getConnection(MYSQL_SERVERURL, MYSQL_USERID, MYSQL_PASSWORD);
                                stmt = conn.createStatement();
                                stmt.executeUpdate(SQL);
                                System.out.println("Executed " + SQL);
                                return;
                            }catch(Exception ex){
                                ex.printStackTrace();
                            }finally {
                                try {
                                    if(stmt != null)
                                        conn.close();
                                } catch(SQLException se) {
                                }
                                try {
                                    if(conn != null)
                                        conn.close();
                                } catch(SQLException se) {
                                    se.printStackTrace();
                                }
                            }
                        }catch(Exception ex){
                            ex.printStackTrace();
                        }
                        finally{
                            return;
                        }
                    }
                });
            }
        }
    });

screenshot

【问题讨论】:

  • 将您的代码精简到显示问题所需的最低限度。

标签: java multithreading threadpool


【解决方案1】:

我建议你学习 Oracle 的 Executors 教程。并在 Stack Overflow 上搜索有关此主题的许多现有问题和答案。

只创建一次执行器服务

不要重复调用Executors.newSingleThreadScheduledExecutor()。每个调用都在创建一个线程池。你永远不会关闭它们。线程继续,甚至可能在您的应用程序终止之后。

您应该在您的应用程序中只实例化一次执行程序服务(通常)。然后将返回的ScheduledExecutorService 对象保存在您的应用程序中的某个位置。

当您有要在后台线程上运行的任务时,检索该现有对象并安排该任务。

最终您必须关闭执行器(及其后备线程池)。

如需更多讨论,请参阅我的this Answer 就一个非常相似的问题。

ScheduledExecutorService 用于调度

您不会延迟安排任务。所以你不需要ScheduledExecutorService

您只需要带有submit 方法的ExecutorService

【讨论】:

    【解决方案2】:

    executorService.shutdown();解决了如下问题

    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(); executorService.execute(new Runnable() { });

    executorService.shutdown();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      相关资源
      最近更新 更多