Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 安全止动螺纹_Java_Multithreading - Fatal编程技术网

Java 安全止动螺纹

Java 安全止动螺纹,java,multithreading,Java,Multithreading,我有一些课: @Component public MyClass { private volatile boolean stopped = false; public void verification() throws Exception { Thread kpiAllThread = getKPIAllThread(); try { for (int i = 0; i < poolSize; i++) {

我有一些课:

@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!");
            }
        });
    }
}

还有一个变量
stopped
,可以从外部设置为
true
。如何在执行此操作时安全停止线程?因此,所有与数据库的连接都将关闭,线程将成功完成?

停止线程的最干净、最安全的规则是,线程中运行的代码应定期检查一个条件(例如,
boolean shouldExit()
)。当代码检测到该条件为真时,它应该停止正在执行的操作并终止

在线程中运行的代码应该经常检查这种情况,以便它能够合理快速地做出反应。根据经验,设置此条件后,线程应在不到一秒钟内退出。该检查通常类似于迭代池大小的for循环中的if(shouldExit())break。但是,
dao.getKpiAll(workingQueue)
看起来可能很长,因此您可能会在
getKpiAll
中进行更多检查

当您执行此检查时,必须确保每次条件变为true时代码都会干净地退出。例如,您可以使用
finally
块来关闭任何连接等。如果在
getKpiAll
期间发生这种情况,那么继续使用
For
循环来处理项目等都没有意义

有时,这可能会变得更加棘手-例如,当线程正在等待网络操作时,您可能需要关闭网络套接字或类似的东西来中断它。在任何情况下,都要避免使用
Thread.stop()
Thread.interrupt()
——请参阅文档说明它们有问题的原因

如果您这样做,您可以随时从线程外部设置条件以请求线程终止。您可以创建类似于
void requestExit()
的代码,并在那里设置一个布尔变量。调用
requestExit()
后,调用
Thread.join()
,并在适当的超时时间内等待线程执行其业务,检查条件并退出。同样,根据经验,超时时间是线程最长反应时间的3-10倍


看起来您已经为此目的设置了
setStopped(boolean stopped)
,但您没有检查它。首先,我将删除参数
stopped
,因为将
false
传递给它没有意义。其次,您需要如上所述添加检查。您可能希望使此变量对
dao
可见-请记住,将其作为同步布尔方法公开比作为布尔字段公开要好得多。

您需要停止以使线程可见,因此建议为线程创建一个类,并使其从runnable继承。然后你可以把包含stopped标志的对象传递给它。@NathanHughes,如果变量
stopped
是从我的类之外设置的,我如何中断我的线程?比如plz。如果使用
try with resources
thread
被中断,所有连接和结果集都将关闭?是的,如果在
try with resources
中打开连接,它应该自动关闭。在这种情况下,编译器实际上会为您添加
finally
块,并在其中调用
close()
。如果需要细粒度控制,请编写一个显式的
try finally
,而不是
try with resources
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;
        }
    }