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

本文讨论了在使用线程池处理任务时如何控制超时和中断线程。传统的JDK stop()方法由于安全性问题已被弃用,建议使用中断机制,由任务本身决定中断点并处理中断。在遇到超时时,调用future.cancel(true)来中断任务。同时,示例代码展示了如何在任务中检查中断状态,确保数据一致性。此外,还提到在for循环中使用Thread.currentThread().interrupted()进行中断判断的重要性。
摘要由CSDN通过智能技术生成

0

0

采纳的答案

引用

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

线程的中断在JDK1.0版本中提供了stop()方法,但这个方法极度不安全,会不管

当前对象的状态而直接释放所有的monitor,结束线程,会导致对象处于错误的状态。

所以已经不被推荐使用。

试想,有个任务,A向B转账10000¥,需要先从A账户上扣款10000¥,再将B账号加

10000¥,如果A账号扣款完,这是从外面强行杀死线程,会导致什么后果?

中止一个线程最好的方式就是使用中断,在外面通知线程中断,线程将中断状态设置

为true,而具体是否要中断,中断时需要如何处理以保证数据状态是正确的,这些

应交给任务自己处理。

在什么地方控制中断,应该任务中控制,由你的业务逻辑决定,就算是

操作数据库也一样可以设置中断点,或者说更应该判断中断点,来决定是否回滚

事务。

2011年9月01日 18:25

0

0

String N= "";

String M= "";

String id= "";

String pwd = "";

protected void doPost(HttpServletRequest req, HttpServletResponse res)

throws ServletException, IOException

{

this.M = req.getParameter("M").trim();

this.N= req.getParameter("N").trim();

this.id = req.getParameter("id").trim();

this.pwd = req.getParameter("pwd").trim();

/................../

}

当多个系统同时调用该servlet的时候,出现了servlet的非线程安全的问题。比如有两个系统同时调用该servlet,代码中的N、M、id、pwd的值会出现,一个线程的数据被另一个线程的数据“覆盖”的问题。

我的问题是,第一:是否跟这几个变量是全部变量有关,如果设置为局部变量会出现这个问题吗?第二:使用多个servlet能解决这个问题,但是是最好的办法吗?

2011年9月15日 11:34

0

0

楼主cancle地方不对,中断异常后返回也有问题,仔细看下面:public class Test {

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

/**

* @param args

*/

public static void main(String[] args) {

Boolean result = false;

Future future = executor.submit(new MyJob());// 将任务提交到线程池中

try {

result = future.get(20, 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();// 出现异常即可终止任务。

[color=red]future.cancel(true);[/color]

}

//executor.shutdown();

System.out.println(result);

}

}

class MyJob implements Callable {

@SuppressWarnings("static-access")

@Override

public Boolean call() {

// do job here

//long startTime = System.currentTimeMillis();

//for (int i = 0; System.currentTimeMillis() - startTime < 2000; i++) {

//System.out.println(i);

//}

try {

Thread.currentThread().sleep(300);

} catch (InterruptedException e) {

e.printStackTrace();

[color=red]return false; [/color]

}

// 模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

2011年9月08日 19:30

0

0

你对自己要做什么可能很清楚,但你对线程池能做什么确实很模糊,自己把自己绕晕了!!!

回滚事务,如果超时事务回滚到操作以前的场景!

2011年9月07日 17:31

0

0

改了一下你原先的代码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;

import java.util.concurrent.Callable;

public class My {

// 业务job

// 实现Callable接口

static class MyJob implements Callable {

public Boolean call() {

// do job here

long startTime = System.currentTimeMillis();

for (int i = 0; System.currentTimeMillis() - startTime < 2000; i++) {

//测试当前线程是否已经中断,配合future.cancel(true)

if (Thread.interrupted())

return false;

}// 模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

/**

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

future.cancel(true);// 中断执行此任务的线程

}

}

}

测试通过,不会打印"continue..."

2011年9月05日 17:43

0

0

package dl.java.iteye;

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;

import java.util.concurrent.Callable;

public class My {

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

/**

* @param args

*/

public static void main(String[] args) {

Boolean result = false;

MyJob job = new MyJob();

Future future = executor.submit(job);// 将任务提交到线程池中

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]常时打印

job.thread.stop();

}

}

//业务job

//实现Callable接口

static class MyJob implements Callable {

public Thread thread = null;

@Override

public Boolean call() throws Exception {

//do job here

long startTime = System.currentTimeMillis(); //获取当前运行线程

thread = Thread.currentThread();

for(int i=0;System.currentTimeMillis()-startTime<2000;i++){}//模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

}

这是一个案例,你根据实际情况,修改吧。你可以复制,运行一下。打印结果:

Time is out

2011年9月05日 15:19

0

0

引用

xiaoyang0601 写道

一个这种的办法是获取MyJob当前的线程;在MyJob对象中声明一个变量thread

Java代码

import java.util.concurrent.Callable;

//实现Callable接口

public class MyJob implements Callable {

public Thread thread = null;   //定义一个当前任务线程

@Override

public Boolean call() throws Exception {

//do job here

long startTime = System.currentTimeMillis();

thread = Thread.currentThread();//获取当前线程,,外界可以访问

for(int i=0;System.currentTimeMillis()-startTime<2000;i++){}//模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

import java.util.concurrent.Callable;

//实现Callable接口

public class MyJob implements Callable {

public Thread thread = null;

@Override

public Boolean call() throws Exception {

//do job here

long startTime = System.currentTimeMillis();

thread = Thread.currentThread();//获取当前线程for(int i=0;System.currentTimeMillis()-startTime<2000;i++){}//模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

在My对象中当超时,就对该工作任务的线程进行终止。

Java代码

Boolean result = false;

MyJob job = new MyJob();//将提交的任务

Future future = executor.submit(job);// 将任务提交到线程池中

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]常时打印

job.thread.stop();//访问MyJob线程。

}

Boolean result = false;

MyJob job = new MyJob();Future future = executor.submit(job);// 将任务提交到线程池中

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]常时打印

job.thread.stop();}

我也想用stop(),但是job.thread取不到该线程啊

能访问到啊。你仔细看看代码。在MyJob中声明一个任务线程,这个任务线程就是当前任务的,在My对象中,声明一个MyJob job = new MyJob();

Future future = executor.submit(job);//

在超时异常代码中

job.thread.stop();是可以访问的。你或许访问修饰符有误。

还有你提的这个问题,中超时不再处理以后的任务,但这个超时的后的任务放在任务中,欠妥,可以提取出来,进行重构,先进性必要的超时处理,如果没有超时在My对象中进行处理业务,如果超时就不再处理。

2011年9月02日 17:10

0

0

一般涉及到网络连接的地方,都会提供超时接口,getConnection也不例外,

不需要自己来控制超时。/**

* Sets the maximum time in seconds that a driver will wait

* while attempting to connect to a database.

*

* @param seconds the login time limit in seconds; zero means there is no limit

* @see #getLoginTimeout

*/

public static void setLoginTimeout(int seconds) {

loginTimeout = seconds;

}

2011年9月02日 16:12

0

0

引用

难道就无解了吗?

暂时没想出来,晚上回去我有开发环境了,我再试试看

2011年9月02日 15:34

0

0

引用

例子很好,不过要在任务中控制,不知道该如何在任务中设置中断点

比如说简单的获取数据库connection,我要在规定时间内判断,若没连接成功就中断线程

因为你获得不到这个JOB所在的线程,所以你没有办法来中断它的。

2011年9月02日 15:26

0

0

引用

我也想用stop()

stop() 已经是不推荐使用了,就算你获得了JOB所在的线程,请也别使用这个方法

2011年9月02日 14:57

0

0

一个这种的办法是获取MyJob当前的线程;在MyJob对象中声明一个变量threadimport java.util.concurrent.Callable;

//实现Callable接口

public class MyJob implements Callable {

[b] public Thread thread = null;[/b]

@Override

public Boolean call() throws Exception {

//do job here

long startTime = System.currentTimeMillis();

[b]thread = Thread.currentThread();[/b]//获取当前线程for(int i=0;System.currentTimeMillis()-startTime<2000;i++){}//模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

在My对象中当超时,就对该工作任务的线程进行终止。

Boolean result = false;

[b]MyJob job = new MyJob();[/b]Future future = executor.submit(job);// 将任务提交到线程池中

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]常时打印

[b]job.thread.stop();[/b]}

2011年9月02日 13:42

0

0

我习惯的做法是在工作线程内部设置一个boolean变量,如果外界想让线程结束就设置一下这个变量。在线程内部会判断这个变量,看是否要退出。

2011年9月01日 21:05

0

0

引用

public class MyJob implements Callable {

@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;

}

}

你这个测试任务写的有问题,根本没有控制中断,for循环会一直执行到结束。

要在循环中加入线程中断的判断。

Thread.currentThread().interrupted()

引用

public class MyJob implements Callable {

@Override

public Boolean call() {

//do job here

long startTime = System.currentTimeMillis();

for(int i=0;System.currentTimeMillis()-startTime<2000;i++){

if(Thread.currentThread().interrupted()){

return false;

}

}//模拟业务执行超过2000毫秒,即已经超时

System.out.println("continue...");

return true;

}

}

在外面执行future.cancel(true)这时就能结束任务了。

2011年9月01日 17:55

0

0

主要是要实现自己的终止策略

比如在for循环中可以加入这样的判断for(;;){

if(Thread.currentThread().isInterrupted())

return false; //这就是来响应future.cancel啊,你不响应他,咋停啊

}

Java 并发编程实践这本书,看了基本上可以解决大部分问题了

2011年9月01日 17:21

0

0

引用

使用thread能实现吗?还要有返回值的

使用 Thread.sleep() 的话,你可以这么写:

try{

Thread.sleep(2000);

} catch (InterruptedException e) {

return false;

}

System.out.println("continue...");

return true;

2011年9月01日 17:18

0

0

你能把你的for循环里面模仿超时的语句贴出来吗?我用的是Thread.sleep();

2011年9月01日 17:05

0

0

引用

是不是使用线程池提交,线程池将任务分配给多个线程处理了,cancel()后仍然将任务分配给其他的线程执行?这个需要看源码啊。但我认为,应该是针对每一个被submit上去的任务开一个线程来执行

2011年9月01日 17:02

0

0

引用

res为true

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

2011年9月01日 16:59

0

0

我验证过了在"time is out"的打印后面加future.cancel(true);是可行的,不知道你怎么验证的?

} catch (TimeoutException e) {

System.out.println("Time is out");//抛出超时异[size=xx-small][/size]常时打印

future.cancel(true);

}

2011年9月01日 16:40

0

0

public class My {

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

public static void main(String[] args) {

Future 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 {

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;

}

}

}

2011年9月01日 16:28

0

0

catch (TimeoutException e) {

System.out.println("Time is out");//抛出超时异常时打印

boolean res = future.cancel(true);

System.out.println("res:" + res);

}

你这么改一下,看看 res 的值是true 还是 false;

2011年9月01日 15:59

0

0

public class My {

private static ExecutorService executor = Executors.newCachedThreadPool();// 定义一个线程池

/**

* @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毫秒的时间内完成

//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);

}

}

需要调用 executor.shutdown();

终止当前线程任务。

2011年9月01日 13:51

0

0

在for循环后面抛个异常这样挺好哈

if (System.currentTimeMillis() - startTime >=2000)

throw new TimeoutException();

或者在你的job里实现取消策略,在需要时自己取消。

Future future = executor.submit(new MyJob());// 将任务提交到线程池中

executor.shutdown();//没人提交了该shutdown()了吧

2011年9月01日 13:07

0

0

引用

catch (TimeoutException e) {

System.out.println("Time is out");//抛出超时异[size=xx-small][/size]常时打印

}

在你的System.out.print()语句下,添加一行代码:

future.cancel(true);

看看行不行

2011年9月01日 12:55

0

0

在外面控制时间,200毫秒后,执行

future.cancel(true);

2011年9月01日 12:09

0

0

这好像没什么好办法

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

2011年9月01日 11:54

8aae5bd772e46b5c641c69ae703a63c3.png

315

0

0

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值