安全停止线程

我有一些课:


@Component

public MyClass {

   private volatile boolean stopped = false; 


   public void verification() throws Exception {


        Thread kpiAllThread = getKPIAllThread();


        try {

            for (int i = 0; i < poolSize; i++) {

                execDispatcher.put(processExecutor.submit(getCheckValuesInKPIConsumerTask(workingQueue)));

            }

            kpiAllThread.start();

        } finally {

            waitFinished();

        }

    }


    public void setStop(bolean stopped) {

         this.stopped = stopped;

    }


    private Thread getKPIAllThread() {

        return new Thread(() -> {

            try {

                LOG.debug("KPIAllThread started!");

                dao.getKpiAll(workingQueue);

                for (int i = 0; i < poolSize; i++) {

                    workingQueue.put(() -> true);

                }

            } catch (Exception ex) {

                LOG.error("KPIAllThread exception: ", ex);

            } finally {

                LOG.error("KPIAllThread finished!");

            }

        });

    }

}

这个类启动生产者线程getKPIAllThread。他从 db 获取数据并放入BlockingQueue.


getKpiAll像这样的方法:


public void getKpiAll(final BlockingQueue<KeyPropertyIndex> kpiData) throws Exception {

        LOG.debug("Starting getKpiAll");

        try (final Connection con = dataSource.getConnection();

             final Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) {

            stmt.setFetchSize(Integer.MIN_VALUE);


            try (final ResultSet rs = stmt.executeQuery(sqlGetAllkpi)) {

                while (rs.next()) {

                    kpiData.put(new KeyPropertyIndexData(rs.getLong(1), rs.getString(2)));

                }

            }

            LOG.debug("Finished get getKpiAll");

        } catch (Exception ex) {

            throw ex;

        }

    }

还有一个变量stopped可以从外部设置到true. 这样做时如何安全地停止我的线程?这样到数据库的所有连接都关闭并且线程成功完成?


爪哇

多线程


烙印99
浏览 128回答 1
1回答

大话西游666

停止线程的最干净和最安全的规则是在线程中运行的代码应该定期检查条件(例如,boolean shouldExit())。当代码检测到这个条件为真时,它应该停止做正在做的事情并终止。在线程中运行的代码应该经常检查这种情况,以便它可以相当快地做出反应。根据经验,设置此条件后线程应在不到一秒的时间内退出。该检查通常看起来类似于if (shouldExit()) break您的 for 循环中的某个地方,它在池大小上进行迭代。但是,dao.getKpiAll(workingQueue)看起来可能很长,因此您可能会在getKpiAll.当您进行此检查时,您必须确保每次条件变为真时您的代码都会干净地退出。例如,您可以使用finally块来关闭任何连接等。如果在 期间发生这种情况getKpiAll,甚至继续for循环来处理项目等都没有意义。有时,这会变得更加棘手 - 即当线程正在等待网络操作时,您可能需要关闭网络套接字或类似的东西来中断它。在任何情况下,避免使用Thread.stop()或Thread.interrupt()- 查看文档为什么它们有问题。如果你做这样的事情,你可以随时从线程外部设置条件来请求线程终止。您可以制作类似的东西void requestExit()并在那里设置一个布尔变量。调用后requestExit(),您Thread.join()使用合适的超时时间调用以等待线程完成其业务,检查条件并退出。同样,根据经验,将超时设置为线程最长反应时间的 3-10 倍。看起来你已经有setStopped(boolean stopped)这个目的,但你没有检查它。首先,我会删除参数,stopped因为传递false给它没有意义。其次,您需要添加如上所述的检查。您可能希望使这个变量可见dao- 请记住,将它作为同步布尔方法公开比作为布尔字段公开要好得多。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java