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
在任务完成后不让程序结束的原因非常感兴趣