-
2020-11-09 14:08:46
如何让java程序执行一段时间后停止
1、概述
在本文中,我们将学习如何在一段时间后结束长时间运行的任务。我们将探讨这个问题的各种解决方案。此外,还将介绍各种方案缺点。
2、使用循环
假设我们在一个循环中处理一组数据,比如电子商务应用程序中循环获取产品项的一些信息,但可能没有必要完成所有项的处理。
实际上,我们希望只处理某一特定时间之前的内容,在此之后,我们希望停止执行,并显示列表在此时间之前处理的内容。
代码例子如下:long start = System.currentTimeMillis(); long end = start + 30*1000; while (System.currentTimeMillis() < end) { // 一些费时的操作 }
在这里,如果时间超过了30秒的限制,循环将中断。在上述解决方案中有一些我们值得注意的地方:
- 结果无法准确预测:循环运行的时间可能超过规定的时间限制。这将取决于每个迭代可能花费的时间。例如,如果每次迭代可能花费7秒,那么总时间可能会增加到35秒,这比期望的30秒时间限制大约多17%。
- 阻塞:在主线程中这样的处理可能不是一个好主意,因为它会阻塞很长一段时间。相反,这些操作应该与主线程解耦。
3、使用中断机制
在这里,我们将使用一个单独的线程来执行长期运行的操作。在超时时,主线程将向工作线程发送一个中断信号。如果工作线程仍然是活的,它将捕获信号并停止执行。如果worker线程在超时之前完成,它将不会对worker线程产生影响。
让我们看看工作线程:
// 实现Runnable线程接口 class LongRunningTask implements Runnable { @Override public void run() { try { while (!Thread.interrupted()) { Thread.sleep(500); } } catch (InterruptedException e) { // log error } } }
在这里,Thread.sleep(500)模拟长时间运行的操作。除了这个,还有其他的操作。检查中断标志很重要,因为不是所有的操作都是可中断的。所以在这些情况下,我们应该手动检查标志。
另外,我们应该在每次迭代中检查这个标志,以确保线程在最多一次迭代的延迟内停止自身执行。
接下来,我们将介绍发送中断信号的三种不同机制。
3.1、使用Timer组件
我们可以创建一个TimerTask在超时时中断工作线程:
class TimeOutTask extends TimerTask { private Thread t; private Timer timer; TimeOutTask(Thread t, Timer timer){ this.t = t; this.timer = timer; } // 用于结束工作线程 public void run() { if (t != null && t.isAlive()) { t.interrupt(); timer.cancel(); } } }
上面我们定义了一个TimerTask,传入工作线程作,timer定时器为参数,它将在调用工作线程的run方法时中断工作线程。定时器会在指定的延迟后触发TimerTask:
// 创建工作线程 Thread t = new Thread(new LongRunningTask()); // 创建定时器,指定时间内结束工作线程 Timer timer = new Timer(); timer.schedule(new TimeOutTask(t, timer), 30*1000); t.start();
3.2、使用Future , get 方法
我们也可以使用Future的get方法来代替Timer:
ExecutorService executor = Executors.newSingleThreadExecutor(); Future future = executor.submit(new LongRunningTask()); try { f.get(30, TimeUnit.SECONDS); } catch (TimeoutException e) { f.cancel(true); } finally { service.shutdownNow(); }
这里我们使用ExecutorService来提交工作线程,该工作线程返回一个Future的实例,Future的get方法将阻塞主线程,直到指定的时间。它将在指定超时后引发TimeoutException。在catch块中,我们通过调用Future对象上的cancel方法来中断工作线程。与前一种方法相比,这种方法的主要优点是它使用一个池来管理线程,而Timer只使用一个线程(没有池)。
3.3、使用ScheduledExcecutorSercvice
我们还可以使用ScheduledExecutorService来中断任务。这个类是ExecutorService的扩展,提供了相同的功能,并添加了几个处理执行调度的方法。这样可以在设定时间单位的一定延迟后执行给定的任务:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); Future future = executor.submit(new LongRunningTask()); executor.schedule(new Runnable(){ public void run(){ future.cancel(true); } }, 1000, TimeUnit.MILLISECONDS); executor.shutdown();
上述代码,我们使用newScheduledThreadPool方法创建了一个大小为2的调度线程池。ScheduledExecutorService.schedule方法接受一个Runnable、一个延迟值和延迟的单位。
上述程序将任务安排在提交后1秒后执行。此任务将取消原来的长时间运行的任务。
注意,与前面的方法不同,我们没有通过调用Future.get方法阻塞主线程。因此,它是上述所有方法中最受欢迎的方法。7、这样停止是万无一失么
并不能保证线程执行在一段时间后停止。主要原因是并不是所有的阻塞方法都是可中断的。事实上,只有少数定义良好的可中断的方法才支持中断。因此,如果线程被中断并设置了标志,那么在它到达这些可中断方法之一之前,不会发生任何其他事情会一直阻塞下去。
例如,读和写方法只有在使用interruptiblnel创建的流上调用时才是可中断的。BufferedReader不是中断机制。因此,如果线程使用它来读取文件,那么在read方法中阻塞的这个线程上调用interrupt()不起作用。但是,我们可以在每次读取循环后显式地检查中断标志。这将为延迟停止线程提供合理的保证。但是,这并不能保证在一段严格时间后停止线程,因为我们不知道读操作需要多少时间。另一方面,Object类的wait方法是可中断的。因此,在wait方法中阻塞的线程将在设置中断标志后立即抛出InterruptedException。我们可以通过在其方法签名中查找抛出InterruptedException来识别阻塞方法。一个重要的建议是避免使用已弃用的Thread.stop()方法。停止线程会导致它解锁它锁定的所有监视器。这是由于向上传播堆栈的ThreadDeath异常造成的。
8、结论
在本文程中,我们总结了在给定时间后停止执行的各种技术,以及每种技术的优缺点。
更多相关内容 -
IntelliJ IDEA调试时点击停止按钮,程序并没有立即停止
2020-11-23 21:43:33调试一段循环更新数据库的程序时,在更新语句处设置了一个断点,明明在更新了一条数据后停止了Debug,但是数据库里的数据却更新了2条。。 IntelliJ IDEA版本信息: IntelliJ IDEA 2019.3.3 (Ultimate Edition) Build...Background
调试一段循环更新数据库的程序时,在更新语句处设置了一个断点,明明在更新了一条数据后停止了Debug,但是数据库里的数据却更新了2条。。
IntelliJ IDEA
版本信息:IntelliJ IDEA 2019.3.3 (Ultimate Edition) Build #IU-193.6494.35, built on February 11, 2020 Licensed to XX Subscription is active until August 17, 2021 For educational use only. Runtime version: 11.0.5+10-b520.38 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Windows 7 6.1 GC: ParNew, ConcurrentMarkSweep Memory: 984M Cores: 4 Registry: debugger.watches.in.variables=false, compiler.automake.allow.when.app.running=true Non-Bundled Plugins: Lombook Plugin, org.intellij.scala
Analysis
经过分析,得出结论:在点击停止按钮时,程序并没有立即终止。以上问题可抽象为下面的“Hello World”。
一个简单的
Hello World
,在打印World这一行设置断点,调试启动,到了断点处,此时控制台已打印出Hello
,这时,直接点击停止,然而,并没有按预期地进行停止?!。赫然打印出了Hello World
public static void main(String[] args) { System.out.print("Hello "); System.out.println("World"); }
Solution
解决方案:在Frames窗口,点击
Force Return
If you have any questions or any bugs are found, please feel free to contact me.
Your comments and suggestions are welcome!
-
matlab如果达成某一条件则停止
2020-06-27 16:50:42 -
LabVIEW实现应用程序停止或退出
2022-04-04 12:51:44我们在做应用程序开发时,最后必然会用到应用程序停止或退出功能,本篇博文将分享实用LabVIEW如何实现应用程序停止或退出。我们在做应用程序开发时,最后必然会用到应用程序停止或退出功能,本篇博文将分享实用LabVIEW如何实现应用程序停止或退出。
其实非常简单,两个组件就可以实现,在LabVIEW中右键鼠标:编程→应用程序控制→可以找到停止和退出LabVIEW,如下所示:
停止功能相当于单击工具栏上的中止执行按钮。输入TRUE可调用该函数前,应确认已完成VI的所有最后任务(例如,关闭文件、设置相关设备的保存值等),停止功能仅仅使程序停止运行,不退出LabVIEW环境。
退出功能和停止功能很相似,但是它停止所有正在执行的VI并结束当前的LabVIEW实例,在使用的时候需要加以区分。
最后通过一个小案例加深理解,通过点击按钮停止定时计数程序,实现代码如下所示:
-
已解决:停止以下一个或多个进程以继续安装:vmware.exe
2021-11-19 09:44:52类似思路:电脑更新qq时,必须将qq关闭,才可以进行更新。 回到VMware安装界面,重新点击下一步。 方法二 1.打开任务管理器,点击“详细信息”选项卡 2.在“详细信息”选项卡中找到... -
从键盘中读入一系列字符,直到输入字母a时停止,打印a之前的所有字符
2019-04-06 11:48:51#include <stdio.h> main() { char c; while((c = getchar())!= 'a') printf("%c", c); } -
Docker 停止容器
2021-08-23 09:43:16使用docker stop停止一个容器 docker stop可以用来终止一个正在运行的容器。它的命令格式如下: docker stop [OPTIONS] Container [Container …] 其中: docker stop: Docker停止容器的命令关键词; OPTIONS:命令... -
Android:Activity之间跳转时停止运行的一种解决办法
2014-11-09 19:25:41最近Android开发过程中由一个activity向某个activity跳转时 -
打开PDF文件时,Windows提示Adobe Reader 已停止工作
2020-12-07 16:30:10打开PDF文件时,Windows提示Adobe Reader 已停止工作 这是因为Adobe软件后台运行导致的。大家可以使用电脑管家、360等软件禁止软件联网即可解决。 找到相应软件后,禁用网络即可。 -
android 控制帧动画停止时,停在第一帧
2017-09-05 09:09:21本文转自:http://blog.csdn.net/minyou_1314/article/details/25230165实现:用Frame Animation 可以在Java代码中添加每一帧的动画,也可以创建动画布局,我用的是创建动画布局。 1.创建动画布局,在drawable... -
解决安装requirements.txt时遇到pip安装失败就停止不会继续往下一个安装的问题
2020-12-23 05:08:58在安装requiirements.txt时,遇到...就像我遇到的一个包使用conda install 后提示我已经安装了,但是我再使用pip install -r requirements.txt时到这个包这里又停住了。使用pip install 这个包时提示找不到对应的版... -
python 接收MQTT间隔一段时间停止问题
2021-11-13 14:09:16我不太清楚是什么问题,就是程序运行一段时间就停止了,也不会报错,有大佬知道是为什么的可以说一下么,谢谢了。下面是我实现的MQTT订阅消息代码。 import paho.mqtt.client as mqtt from datetime import ... -
运行程序时,“python 已停止工作”的解决方法
2020-03-17 22:24:04Windows下,运行python程序时,出现 如下图所示的“python 已停止工作”: 需要注意有可能是代码有问题。 当我把我的地址代码 train_dir = 'F:/www/eg_pic' 改成 train_dir = 'F:/www/eg_pic/' 时,即在地址的最后... -
Unity 之 关于停止协程的五种方式解析
2021-04-21 10:03:52通过代码结合示例一一解析了五种停止协程的方式。 -
VS出现一个问题导致程序停止正常工作,请关闭该程序。
2019-01-22 09:41:27在VS调试运行过程中可能会出现些许问题,随之会提示关闭程序、重新启动程序、关闭程序等。可以通过以下方法进行修复: 1、通过控制面板里面的卸载程序,找到VS右键更改,随后会有提示。 2、工具 → 导入和导出设置 ... -
解决安装office2013时出现Microsoft setup bootstrapper已停止工作问题
2020-10-29 10:38:59**问题出现背景:**不小心删除office2013安装后的文件导致office软件无法使用,重新安装时出现还问题。 **问题解决方法:**首先,卸载老的office;然后再安装不再出现Microsoft Setup Bootstrapper已停止工作的问题... -
VS2019 禁止Web项目停止调试后自动关闭浏览器(在浏览器窗口关闭时停止调试程序,在调试停止时关闭浏览器)
2020-05-19 08:37:55“编辑并继续”是一种省时的功能,使你能够在程序处于中断模式时更改源代码。通过选择执行命令(如 "继续" 或 "单步执行")继续执行程序时,"编辑并继续" 会自动应用代码更改,但有一些限制。这允许你在调试会话期间... -
解决PyCharm的Python.exe已经停止工作的问题
2021-01-13 12:47:29解决PyCharm的Python.exe已经停止工作的问题今天遇到一个问题,就是用pycharm运行python程序,老是会出现Python.exe已停止的对话框。后来我到处在网上搜原因,网上给出的解决办法也有很多种。最终帮我解决问题的就是... -
解决本地计算机上的MySQL80服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
2022-05-08 14:58:23解决本地计算机上的MySQL80服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止! -
docker启动停止操作命令
2019-06-26 23:59:23上一篇我们简单说明了docker的常用操作命令,下面来说说docker是如何操作一个镜像的,以及镜像交互的基本命令, 1、按照之前所说,远程下载一个镜像,这里从dockerhub上下载一个centos的镜像, docker pull centos ... -
【K8S】优雅停止Pod
2020-01-06 14:32:13优雅停止(Graceful shutdown)这个说法来自于操作系统,比如我们windows关机系统首先会退出软件然后一步步到达关机,而相对的就是硬终止(Hard shutdown),简单的理解就是直接拔电源 到了微服务中,网关会把流量分配... -
【解决】mysql本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止
2021-12-29 17:54:45最近写一个Java Web的项目,需要用到 mysql 数据库,在计算机管理中启动时,发现 mysql 报错:mysql本地计算机上的MySQL服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止。该问题的解决方式为: 1 ... -
Eclipse:停止运行代码(java)
2021-03-14 22:21:45有时,我会运行一个偶然包含无限循环之类的程序。...这里似乎缺少一种非常基本的方法:不要忘记,可以在需要时使用代码中的System.exit终止程序(不需要devops脚本) )。 在这里阅读更多关于它的信息:sta... -
Microsoft Office Excel 已停止工作
2021-07-05 09:44:05出现microsoftofficeexcel已停止工作后,我们关闭表格,进入桌面。 在桌面,我们在开始菜单位置右键。 右键上拉选项中,我们找到且打开”控制面板“。 打开这个选项即进入控制面板。 在控制... -
英雄联盟停止运行_LOL启动游戏提示~league of legends已停止工作是什...
2021-08-10 01:37:02LOL停止工作一、缺少DLL文件以及相关的游戏运行组件,可以使用WeGame或者驱动精灵检测二、系统不兼容,建议使用兼容模式运行三、杀毒软件禁止服务项,可以自行查看四、有最近更新的补丁,建议全卸了五、内存过小,... -
UART(一)——起始位,停止位,奇偶校验位,数据位等概念
2020-09-09 10:09:331. 概念 通用异步收发传输器...传输的格式数据如下图所示: 串口波特率为9600,1bit传输时间大约为104us,传送一个数据实际是10个比特(开始位,8个数据位,停止位),一个bytes传输速率实际为9600*8/10=7680bps。 -
在animate执行时如何停止
2017-10-16 13:38:40为这个弹框添加一个鼠标mouseover,计数清零,进度框的animate也停止并回退,设计如图: $(".popup").mouseover(function(){ clearInterval(timer); $(".progress").stop(); }) .popup就是弹框,.progress... -
linux下如何启动/停止/重启mysql:
2021-05-16 19:29:08一、启动方式1、使用linux命令service 启动:service mysqld start2、使用 mysqld 脚本启动:/etc/inint.d/mysqld start3、使用 safe_mysqld 启动:safe_mysqld&二、停止1、使用 service 启动:service mysqld ... -
Dev c++调试时停止工作解决方法
2017-09-08 11:09:10第一步: 编译器这里要选debug的第二部: 工具-编译选项-程序 gcc那行后面补充 -g -
【Docker 那些事儿】如何安全地停止、删除容器
2022-06-15 09:56:33如何停止、删除容器和对容器进行资源限制