关于使用线程池控制任务超时的问题

[size=large]实现一个在规定的时间内完成一个任务,使用线程池实现,如果在规定的时间内,没完成,即结束该线程任务。以下是我的代码:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class My {
private static ExecutorService executor = [b]Executors.newCachedThreadPool()[/b];//定义一个线程池
/**
* @param args
*/
public static void main(String[] args) {
Boolean result = false;
Future future = executor.submit(new MyJob());//将任务提交到线程池中
try {
result = future.get(200, TimeUnit.MILLISECONDS);//设定在200毫秒的时间内完成
} catch (InterruptedException e) {

        e.printStackTrace();
    } catch (ExecutionException e) {

        e.printStackTrace();
    } catch (TimeoutException e) {
        System.out.println("Time is out");//抛出超时异[size=xx-small][/size][size=large][/size]常时打印
    }
}

}

//业务job
import java.util.concurrent.Callable;
//实现Callable接口
public class MyJob implements [b]Callable[/b] {

@Override
public Boolean call() {
    //do job here
    long startTime = System.currentTimeMillis();
    for(int i=0;System.currentTimeMillis()-startTime<2000;i++){}//模拟业务执行超过2000毫秒,即已经超时
    System.out.println("continue...");
    return true;
}

}

执行void函数时输出结果如下:
Time is out
continue...

这和我的要求不符,我原本是希望在抛出异常之后任务即结束,不再执行System.out.println("continue...");
请问如何解决[/size]

0

27个回答

[quote]在这个job中的call方法应为有for()循环可以找到在哪中断线程,但是如果只是在连接数据库的话,那就无法知道执行到哪,应该加入中断线程的代码,这应该在外面控制,而不应该在job里面实现中断[/quote]

线程的中断在JDK1.0版本中提供了stop()方法,但这个方法极度不安全,会不管
当前对象的状态而直接释放所有的monitor,结束线程,会导致对象处于错误的状态。
所以已经不被推荐使用。

试想,有个任务,A向B转账10000¥,需要先从A账户上扣款10000¥,再将B账号加
10000¥,如果A账号扣款完,这是从外面强行杀死线程,会导致什么后果?

中止一个线程最好的方式就是使用中断,在外面通知线程中断,线程将中断状态设置
为true,而具体是否要中断,中断时需要如何处理以保证数据状态是正确的,这些
应交给任务自己处理。

在什么地方控制中断,应该任务中控制,由你的业务逻辑决定,就算是
操作数据库也一样可以设置中断点,或者说更应该判断中断点,来决定是否回滚
事务。

0

这好像没什么好办法

future.get(200, TimeUnit.MILLISECONDS)这个只是等结果的时间

0

在外面控制时间,200毫秒后,执行
future.cancel(true);

0

[quote]
catch (TimeoutException e) {
System.out.println("Time is out");//抛出超时异[size=xx-small][/size]常时打印
}
[/quote]
在你的System.out.print()语句下,添加一行代码:
[code="java"]
future.cancel(true);
[/code]
看看行不行

0

在for循环后面抛个异常这样挺好哈
if (System.currentTimeMillis() - startTime >=2000)
throw new TimeoutException();
或者在你的job里实现取消策略,在需要时自己取消。

Future future = executor.submit(new MyJob());// 将任务提交到线程池中
executor.shutdown();//没人提交了该shutdown()了吧

0

[code="java"]
public class My {
private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

/**
 * @param args
 */
public static void main(String[] args) {
    Boolean result = false;
    Future<Boolean> future = executor.submit(new MyJob());// 将任务提交到线程池中
    try {
        result = future.get(200, TimeUnit.MILLISECONDS);// 设定在200毫秒的时间内完成

// future.cancel(true);
} catch (InterruptedException e) {

        e.printStackTrace();
    } catch (ExecutionException e) {

        e.printStackTrace();
    } catch (TimeoutException e) {
        System.out.println("Time is out");// 抛出超时异[size=xx-small][/size]常时打印
        executor.shutdown();//出现异常即可终止任务。
    }
    executor.shutdown();
    System.out.println(result);
}

}
[/code]

需要调用 executor.shutdown();
终止当前线程任务。

0

[code="java"]
catch (TimeoutException e) {
System.out.println("Time is out");//抛出超时异常时打印
boolean res = future.cancel(true);

System.out.println("res:" + res);
}
[/code]
你这么改一下,看看 res 的值是true 还是 false;

0

[code="java"]
public class My {

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池
public static void main(String[] args) {
    Future<Boolean> future = executor.submit(new MyJob());// 将任务提交到线程池中
    executor.shutdown();  //关闭线程池 不允许再提交任务,并不是关闭线程池中的线程
    try {
        future.get(200, TimeUnit.MILLISECONDS);// 设定在200毫秒的时间内完成
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (TimeoutException e) {
        future.cancel(true);//关闭超时的这个任务
        //executor.shutdownNow(); //因为这个任务超时,终止了所有的线程.
        System.out.println("Time is out");// 抛出超时异[size=xx-small][/size]常时打印
    }
}

/**
 * 
 * 任务。其实完全可以或应该在任务重控制自己何时超时,
 * 当然我顺着你的思路来了
 */
public static class MyJob implements Callable<Boolean> {

    public Boolean call() throws Exception {
        long startTime = System.currentTimeMillis();

        try {
            TimeUnit.MILLISECONDS.sleep(200);
        } catch (InterruptedException e) {
            return false;   //这里要响应future的中断啊,
                            //返回false吧,或者超时了抛个异常也行,这就是所谓的中断策略
                            //Java5以后的线程终止方法被废了,很多时候终止策略应该自己来实现
        }
        System.out.println("continue...");
        return true;
    }

}

}
[/code]

0

我验证过了在"time is out"的打印后面加future.cancel(true);是可行的,不知道你怎么验证的?
} catch (TimeoutException e) {
System.out.println("Time is out");//抛出超时异[size=xx-small][/size]常时打印
future.cancel(true);
}

0

[quote]res为true[/quote]
呃,那这就奇怪了啊。明明任务已经被取消了,怎么还会打印出下面那句话呢。郁闷啊。。。

0
共27条数据 1 3 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Java定时线程池停止超时任务
一、背景 题主最近遇到一个问题,本来通过ScheduledExecutorService线程池定时调度一个任务。奈何不知道为啥跑了2个多月,其中一个任务Hang住了,那定时的任务则出现了问题。 关于定时线程池,好多人任务设置好频率(比如1Min),它会按照这个间隔按部就班的工作。但是,如果其中一次调度任务卡住的话,不仅这次调度失败,而且整个线程池也会停在这次调度上。 我们先从一个例子试着复现...
java 多线程管理线程任务,根据优先级执行 任务超时管理 线程同步执行管理
需求 需要根据优先级执行任务,有任务不是特别重要,可以稍后执行;需要对正在执行的线程做超时监控;有的API依赖任务返回结果,线程池执行的时候任务也支持同步任务; 简单测试 创建一个使用支持优先级队列(new PriorityBlockingQueue&amp;amp;lt;&amp;amp;gt;() )的线程,然后每个任务实现 java.lang.Comparable 接口 new ThreadPoolExecutor...
设计一个线程超时终止的线程池
原贴地址:点击打开链接 起因是公司有一个定时任务,对于几千的VPN,做一个端口映射,去取得对方客户的硬件信息,做一个监控。 但是部分VPN会连接不通,等待的时间又过长,所以设计这么一个线程池。 原贴提供了一个线程超时终止的实现方式,我再在这个基础上,整理成一个线程池。 首先是线程超时终止 import java.util.concurrent.Callable; pub
《SpringBoot从入门到放弃》之第(十三)篇——使用@Async异步调用,ThreadPoolTaskScheduler线程池,使用Future以及定义超时
本篇博客是在上一篇《SpringBoot从入门到放弃》之第(十二)篇——使用@Async实现异步调用的基础上继续的。 创建 TaskPoolConfig 类,配置线程池: package com.test.util; import org.springframework.context.annotation.Bean; import org.springframework.context....
使用CompletionService批处理任务(线程池阻塞线程)
如果你向Executor提交了一个批处理任务,并且希望在它们完成后获得结果。为此你可以保存与每个任务相关联的Future,然后不断地调用timeout为零的get,来检验Future是否完成。这样做固然可以,但却相当乏味。幸运的是,还有一个更好的方法:完成服务(Completion service)。 CompletionService整合了Executor和BlockingQueue的功能。...
JAVA利用线程池控制方法执行时间
package cn; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import ja...
自制线程池2(限制最长执行时间、回调函数)
  在自制线程1中,我们实现了一个,用于低优先级,可设定最大执行线程,可在执行任务过程或是在队列中的任务时销毁的线程不耻,主要应用于需要花费时间较长的任务的工作。   任务执行的时间长了,说不定因为某些原因,线程执行的任务就死在那了,针对这点加入这样一个功能,记录这个任务执行开始的时间,当它执行的时间如果超过了1h,我们就认为这个工作超过我们的预期了,将它Abort掉。并掉用回调函数ErrCall...
Hystrix生产环境中的线程池大小以及Timeout超时时长优化经验总结
注:发现一篇好文章忍不住分享一下 PS:感觉写的格式有点乱,整理了一下,并加上了一些自己的看法   原文:https://blog.csdn.net/kang123488/article/details/79512226 一、生产环境线程池的配置的问题     生产环境里面,一个是线程池的大小怎么设置,timeout时长如果设置不合理的话,会出现很多问题         1.超时时间太短低于服...
springboot之多任务并行+线程池处理
最近项目中做到一个关于批量发短信的业务,如果用户量特别大的话,不能使用单线程去发短信,只能尝试着使用多任务来完成!我们的项目使用到了方式二,即Future的方案 Java 线程池 Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 ...
线程池使用FutureTask时候需要注意的一点事
8.4 线程池使用FutureTask时候需要注意的一点事 线程池使用FutureTask的时候如果拒绝策略设置为了 DiscardPolicy和DiscardOldestPolicy并且在被拒绝的任务的Future对象上调用无参get方法那么调用线程会一直被阻塞。 问题复现 下面就通过一个简单的例子来复现问题: public class FutureTest {
线程池中多线程设置超时退出监控
前言 在写多线程程序时,大多数情况下会先excutor创建线程池,然后再创建线程,但是对一些读数据库或者其他IO操作,容易堵住线程,此时就需要给线程设置超时时间,干掉超时的线程再重新拉起一个线程来,但是java线程创建并没有预留超时参数,研究了一下网上也没找到好的解决方案,干脆自己想办法搞了一个。 方案 监控线程往往有这么几种方案首先想到的应该就是future的get方法,有超时时间设置参数
线程池引起的jvm内存过大问题
     之前的一个hbase表结构和rowkey规划不合理,我重新设计了一个新的hbase表,需要把旧表的数据写入到新表中,采用的方案是一个region一个region的倒数据,这样旧表的读是scan顺序读,新表的写是随机写,整体速度相对较快。     读采用单线程,写采用线程池(Executors.newFixedThreadPool()),改进scan查询速度的caching配置设置为...
监控ThreadPoolExecutor具体Task在Queue中等待时间
可监控_ThreadPoolExecutor 主要关心的问题:* 最关心的监控数据: * 1.task队列中等待时间 * 2.task任务执行时间 * * 两种方案: * 1. future_task * 2. queue * 注意:因使用Q_config,需要spring_bean管理起来处理: 继承,初始化构造方法private static MonitoringLinkedBlockingQ
用一个线程池执行多个任务
今天写了些代码,测试了一下用多个线程来执行多个任务的的情况,线程放在一个线程池里进行管理。 线程的数量控制在10个(当然可以指定线程池里的线程数量);任务的数量不做限制。   下面贴出代码,以备用时之需。   4个java类:1 Test.java(用于测试);2 TracingObject.java(用于传递参数的对象); 3 TracingTask.java(任务) 4 Tr
java 线程池面试题
Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的资源来创建和驻留在进程中,并且可以共享进程中的资源。 2. 多线程编程的好处是什么?  在多线程程序中,多个线程被
Java使用线程池批量顺序执行任务
使用线程池批量顺序执行任务 AtomicInteger、CountDownLatch、ThreadPoolExecutor组合使用package tool.thread;import com.alibaba.fastjson.JSON; import org.slf4j.Logger; import org.slf4j.LoggerFactory;import java.util.List; im
c++版线程池和任务池示例
转自:http://www.jb51.net/article/47553.htmg++ * -lpthread -o test_threadpool ./test_threadpool 200 20 10 2 20 fun 1=20 fun 1=40 fun 1=60 fun 1=80 fun 1=100 fun 1=120 fun 1=140 fun 1=160 fun 1=180 total t
Java任务调度线程池ScheduledThreadPoolExecutor原理解析
  ScheduledThreadPoolExecutor是JDK在ThreadPoolExecutor的基础上实现的任务调度线程池。   ScheduledThreadPoolExecutor的构造函数全部是调用父类(也就是ThreadPoolExecutor)的构造函数。其中,核心线程数是必须设置的,最大线程数是Integer.MAX_VALUE,空闲工作线程生存时间是0,阻塞队列是Dela...
Java 多线程设置线程超时时间之 Callable接口和Future接口 超时控制
Callable接口和Future接口介绍         在Java中,如果需要设定代码执行的最长时间,即超时,可以用Java线程池ExecutorService类配合Future接口来实现。 Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步计算。
线程池ExecutorService 中并发数的(引入信号量Semaphore)控制执行
查看本机处理器的核心数代码:Runtime.getRuntime().availableProcessors() 所以,应用程序的最小线程数应该等于可用的处理器核数。如果所有的任务都是计算密集型的,则创建处理器可用的核心数那么多线程就可以了。在这种情况下,创建更多的线程对程序性能而言反而是不利的。因为当有多个任务处于就绪状态时,处理器核心需要在线程间频繁进行上下文切换,而这种切换对程序性能损耗
Java并发编程之线程池任务监控
Java并发编程之线程池任务监控   当我们提交runnable或者callable到ThreadPoolExecutor时,我们是无法知道这些任务是在什么时候才真正的执行的,为了实现这个需求,我们需要扩展ThreadPoolExecutor,重写beforeExecute和afterExecute,在这两个方法里分别做一些任务执行前和任务执行后的相关监控逻辑,还有个terminate
定时线程池执行任务时任务执行时间与定时关系
当执行时间小于定时时间的时候: System.out.println(&quot;执行的时间小于设定的周期&quot;); ScheduledExecutorService service = Executors.newScheduledThreadPool(1); service.scheduleAtFixedRate(new Runnable() { @Override public voi...
疯狂Java学习(86)-----------使用CompletableFuture处理异步超时
一天,我在改进多线程代码时被Future.get()卡住了。 public void serve() throws InterruptedException, ExecutionException, TimeoutException { final Future responseFuture = asyncCode(); final Response response = respons
java线程池(newFixedThreadPool)线程消失疑问?
使用executorService提交(submit)线程任务时,若任务执行过程中抛出未被捕获的RuntimeException或error时,会造成这条线程终止吗? 比如若原来线程池中有五条线程,抛出这样的异常时就变成了4条,以此类推,最后这个线程池中就没有线程了。是这样吗?求大神解答 ps: 就是之前自己实验了一下new了一个只有1个线程的线程池,然后不断的向线程池中提交任务,然后在任
C#线程池的使用需要注意的地方
https://blog.csdn.net/u014511737/article/details/47440495
Java并发编程——线程池的使用(三)线程池执行任务、取消任务
一、线程池执行Runnable任务 executor.execute(runnable) executor.execute(new Runnable() { @Override public void run() { System.out.println("执行任务"); }
未整理--大数据处理系列之(一)Java线程池使用, Java 使用线程池执行大数据量统计任务
https://www.cnblogs.com/cstar/archive/2012/06/14/2549494.html https://blog.csdn.net/difffate/article/details/77149901 https://blog.csdn.net/qiyongkang520/article/details/47904863 https://blog.csdn....
面试官常问的线程池,你真的了解吗?
在我们的开发中“池”的概念并不罕见,有数据库连接池、线程池、对象池、常量池等等。下面我们主要针对线程池来一步一步揭开线程池的面纱。使用线程池的好处1、降低资源消耗:可以重...
ExecutorService+FutureTask实现程序执行超时监控
场景描述:一个程序如果超过5秒还未执行完成,希望调用别的程序实现该功能  解决方法:用户ExecutorService+FutureTask实现超过一定时间后,自动执行下面程序 优点:对程序的执行时间进行控制、处理 缺点:如果A程序是一个死循环,FutureTask.get(int,String)停止等待A程序的结果,自动执行下面程序,但A程序会一直执行 以下是实现代码: public
线程池使用中出现的问题
背景 应用中有一个定时任务,轮询一张表的数据(task)处理每个task,每个task都会用线程池来处理,如下, A方法: 其中每个sync的方法中有如下调用, B方法: 即在A方法中异步调用B方法,B方法异步调用了C方法,且B方法中使用了countDownLanch来等待所有的子任务(C方法)执行完成。 那么当我的A方法被多个task调用多次时就会出现死锁问题,详细如下: 线...
spring quartz使用多线程并发“陷阱”
定义一个job:ranJob,设置每秒执行一次,设置不允许覆盖并发执行   &amp;lt;bean id=&quot;rankJob&quot; class=&quot;com.chinacache.www.logstat.job.RankJob&quot; /&amp;gt; &amp;lt;bean id=&quot;rankJobDetail&quot; class=&quot;org.springframework.scheduling.quartz.Method...
自定义实现Java线程池-完善异常处理和去除同步
本篇文章将延续上篇文章的思路继续完善线程池执行功能,主要完善execute方法线程安全的前提下去除同步锁和对任务执行异常的处理,上篇文章最终代码如下: @Override public void execute(Runnable command) { // 校验参数有效性 if (command == null) throw new NullPointerException(&amp;quot;com...
线程池与阻塞队列
前言     上一篇文章中我们将ThreadPoolExecutor进行了深入的学习和介绍,实际上我们在项目中应用的时候很少有直接应用ThreadPoolExecutor来创建线程池的,在jdk的api中 有这么一句话“但是,强烈建议程序员使用较为方便的 Executors 工厂方法Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)、 Exec...
同步锁与线程池的奥秘
第二篇 同步锁: 当多个线程操作临界资源时,可能会出现线程安全隐患问题。 临界资源可能是: (1)某一个静态变量 (2)某一个实例变量 如果想解决这样的问题,需要使用同步操作: 异步操作:多线程的并发操作,相当于各干各的。   前提:有多个线程时 同步操作:在并发基础上,同一个方法内两行代码执行时间片段可以不挨着,但是其他线程不能对这两行代码有执行权,保证了代码的原子性。即这...
Spring 线程池定时监控
在上一篇Spring异步线程池:https://blog.csdn.net/timchen525/article/details/80672186,该文介绍了如何使用Spring的注解来配置异步线程操作。本篇博文中,补充介绍如何通过Spring定时任务来配置定时检测线程池的使用情况。ThreadPoolExecutor线程池提供了如下几个方法:getTaskCount():线程池已执行和未执行的任...
带指定时间执行的线程池
有这样的一个需求: 1、需要一个线程池(Java 1.4); 2、加入的线程可以指定不同的执行时间; 3、当执行时间到且线程池没满,则立即执行该线程; 4、如果执行时间到但线程池已满,则像普通的线程池一样阻塞直到线程池中有可用的位置。   下面是写出来的代码,包含简单的测试。   import java.util.Date; import java.util.Vector; import java...
一个关于多线程池任务配合的项目的总结
11月接了两个小项目的开发任务,时间有点紧,代码还有很多可以优化的地方 项目一 需求,纯后台项目,开发一个自动功能每日定时获取数据库里前一天某些数据,发送到外部系统交互,得到返回结果之后将结果记录回数据库。 项目选用框架 Spring集成quarz来完成定时任务一直是我第一选择。数据库框架,选用了mybatis进行集成,虽然我一直偏爱jdbcTemplate和JPA。   技术处理
线程池使用ExecutorService 多线程处理队列任务
最近转到银行工作,在做最核心的财务账务部分,对我来说是一个比较新的东西,工作也已经四年有余,接触一些新的东西,也是不错,每天也累得像狗...,不说了。/捂脸 接下来说一种非常实用的多线程操作模式,此方式能够应对大部分的多线程操作,稍微改一下往里面套就可以满足大部分的业务需求。 基本方式是: 使用ExecutorService 管理多线程,使用Executors创建newFixedThrea
使用线程池控制Phoenix连接超时
HBase – Hadoop Database,一个NoSQL数据库,可存储大量非关系型数据,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。 Phoenix是构建在HBase上的一个SQL层,能让我们用标准的JDBC API而不是HBase客户端API来对HBase数据进行操作。 HBase,可以用shell进行操作,也可以用Java api进行操作。HB
线程池任务添加流程
一个任务进来,如果核心线程未满,则创建核心线程来执行,如果核心线程已满则放到阻塞队列中,如果阻塞队列已满未达到最大线程数,则创建非核心线程来处理任务,如果达到最大线程数则拒绝任务。ExecutorService 提供了两种提交任务的方法:execute():提交不需要返回值的任务submit():提交需要返回值的任务有两个方法关闭线程池:`shutdown() 将线程池的状态设置为 SHUTDOW...
文章热词 机器学习教程 Objective-C培训 交互设计视频教程 颜色模型 设计制作学习
相关热词 mysql关联查询两次本表 native底部 react extjs glyph 图标 关于大数据培训 关于云计算