Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 ScheduledExecutorService-程序在一次性操作后未结束_Java_Multithreading_Scheduled Tasks_Java 8_Scheduledexecutorservice - Fatal编程技术网

Java ScheduledExecutorService-程序在一次性操作后未结束

Java ScheduledExecutorService-程序在一次性操作后未结束,java,multithreading,scheduled-tasks,java-8,scheduledexecutorservice,Java,Multithreading,Scheduled Tasks,Java 8,Scheduledexecutorservice,我的程序中有一个预定任务,在给定的时间段后关闭一个帧。但是,在执行任务后,程序将继续运行,就好像ScheduledExecutorService仍在另一个线程上运行一样 这是我的代码的相关部分: int delay = 1000; ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(); ex.schedule(() -> { System.out.println("executed"

我的程序中有一个预定任务,在给定的时间段后关闭一个帧。但是,在执行任务后,程序将继续运行,就好像
ScheduledExecutorService
仍在另一个线程上运行一样

这是我的代码的相关部分:

int delay = 1000;

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
ex.schedule(() -> {

    System.out.println("executed");
    getWindow().closeWindow();
    // ex.shutdown();

}, delay, TimeUnit.MILLISECONDS);
在这里,任务在1秒延迟后执行,“executed”打印一次,帧关闭,程序即使在该代码之后仍保持运行。如果我取消注释
ex.shutdownNow(),程序按预期成功结束。然而,我不明白为什么会发生这种情况。我也没有从互联网的其他地方找到任何东西

MCVE:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Main {

    public static void main(String[] args) {
        int delay = 1000;

        ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
        ex.schedule(() -> {

            System.out.println("executed");
            // ex.shutdown();

        }, delay, TimeUnit.MILLISECONDS);
    }

}

lambdas可能已经放弃了它,但这确实是Java8


为什么程序在任务执行后没有停止?

执行者返回的
ScheduledExecutor服务
线程池#newSingleThreadScheduledExecutor()
使用非守护进程线程。在关闭线程池之前,这些线程仍处于活动状态,等待执行任务。当非守护进程线程处于活动状态时,JVM不会结束


您可以使用重载的
执行器#newSingleThreadScheduledExecutor(ThreadFactory)
并提供自己的
ThreadFactory
实现来创建守护进程线程。请注意,这有可能导致任务甚至无法运行,因为JVM将在任务的计划时间之前退出

照你发现的去做,把它关掉。请注意,您应该始终在操作不会失败的安全位置关闭它。

。和
Executors.defaultThreadFactory()
将每个新线程创建为非守护进程线程。但是,
Executors.newSingleThreadScheduledExecutor()超载
ThreadFactory
作为参数,如果您愿意尝试该方向

    public static void main(String[] args) {
        int delay = 1000;

        class DaemonFactory implements ThreadFactory
        {
            @Override
            public Thread newThread(Runnable r)
            {
                Thread t = new Thread(r);
                t.setDaemon(true);
                return t;
            }
        }

        ThreadFactory tf = new DaemonFactory();
        ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor(tf);
        ex.schedule(() -> {
            System.out.println("executed");
        }, delay, TimeUnit.MILLISECONDS);
    }

我将以完全不同的方式处理这一问题。你说:

我的程序中有一个预定任务,在给定的时间段后关闭一个帧

为什么不为此使用Swing计时器,因为它是为了与Swing事件线程很好地工作而构建的

new Timer(1000, new ActionListener() {

    public void actionPerformed(ActionEvent e) {
        ((Timer) e.getSource()).stop();
        someWindow.dispose();        
    }

}).start();

您可以从ScheduledExecutorService调用shutdown,因为它将等待线程执行,然后完成线程池。正如您在Javadoc中所看到的:“启动有序关机,在此过程中执行以前提交的任务,但不会执行新任务 已被接受。如果调用已关闭,则不会产生其他影响。“

例如:

...
scheduledExecutorService.schedule(runnable, delay, TimeUnit.MILLISECONDS);
scheduledExecutorService.shutdown();
...

我从onCreate()启动调度器,并使用onDestroy()方法停止它,以停止调度器服务

public MyActivity extends Activity
{
ScheduledExecutorService scheduledExecutorService;
    ScheduledFuture<?> scheduledFuture;
    private int apiThreshold = 10;//seconds


onCreate()
{
    startScheduler();
 }

onDestroy()
{
    if (scheduledFuture != null) 
{ 
 stopScheduler(); 
}
 shutDownService();
  super.onDestroy();
 }

 public void startScheduler() {
        Debug.e(TAG, "inside start scheduler");
        scheduledExecutorService = Executors.newScheduledThreadPool(1);

        scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                // call method to do your task/perform your repeated task
            }
        }, 4, apiThreshold, TimeUnit.SECONDS);
    }


public void shutDownService()
    {
        if (scheduledExecutorService != null) {
            Log.e(“test,"in shutDown service close if not null");
            scheduledExecutorService.shutdownNow(); // shutdown will allow the final iteration to finish
            // executing where shutdownNow() will kill it immediately

            Log.e(“test,"is service shutdown(true/false)=="+scheduledExecutorService.isShutdown());
        }
    }

 }
public MyActivity扩展活动
{
ScheduledExecutorService ScheduledExecutorService;
计划的未来计划的未来;
private int apirthreshold=10;//秒
onCreate()
{
startScheduler();
}
onDestroy()
{
if(scheduledFuture!=null)
{ 
stopScheduler();
}
关闭服务();
super.ondestory();
}
公共无效startScheduler(){
Debug.e(标签,“内部启动调度器”);
scheduledExecutorService=Executors.newScheduledThreadPool(1);
scheduledFuture=scheduledExecutorService.scheduleAtFixedRate(新的可运行(){
@凌驾
公开募捐{
//调用方法来执行任务/执行重复的任务
}
},4,API阈值,时间单位。秒);
}
公共服务
{
if(scheduledExecutorService!=null){
Log.e(“测试,关闭关闭服务,如果不为空”);
scheduledExecutorService.shutdownNow();//关闭将允许最终迭代完成
//执行where shutdownNow()将立即终止它
Log.e(“test”,是服务关闭(true/false)=“+scheduledExecutorService.isshutton());
}
}
}

在提交所有任务后,您应该调用执行器上的
shutdown()
,而不是
shutdownNow()
。这是根据@HovercraftFullOfEels的命令。啊,是的,我知道。不过这与此无关。不要在意:)我会随时编辑它,但是
shutdown()
调用不是无关的,您的代码需要它。@HovercraftFullOfEels它是无关的。这是一个好观点,但不是我要问的。我要问的是,为什么程序不调用
关闭方法就不会结束,但它是非常相关的。再次,请阅读我给您的API链接,看看原因。这是完整的答案对于你的所有问题。令人沮丧的是…我仍然需要等待3分钟才能接受这个问题。当你在做这件事时,你能提供一个更安全的地方的例子吗?@olavimutanoja这有点棘手,但不知道你整个应用程序的布局。我已经重新编写了我的答案。我对swing(或一般的UI编程)了解不够.@SotiriosDelimanolis如果提供的MCVE是我的整个应用程序,你能提供一个简单的例子吗?我相信我以后可以将这个例子应用到我的实际程序中。@OlaviMustanoja你的MCVE很好。我担心
getWindow().closeWindow()之类的事情<或代码>,其中可能是<代码> null <代码>,也可以引发异常。在这种情况下,您希望有一个<代码>最后< /Cord>块,在其中执行<代码>关闭/代码>。再次,我不知道用非命令行GUI的应用程序。您可能想考虑用<代码>系统关闭进程。退出(0)
。请注意,由于JVM将在任务的计划时间之前退出,这可能会导致任务无法运行。@SotiriosDelimanolis Fair point。但是,当程序不在程序之外执行任何操作(如文件IO、数据库连接等)时,这并不重要实际上,我是在发布问题后才这样做的。不过,我决定不编辑我的帖子,因为我对
ScheduledExecutorService
在任务完成后不让程序结束的原因非常感兴趣