在一个线程里执行一个长时间的任务,比如数据库操作,我想在设定的时间内如果还没有执行完,立刻中止该线程。
以下是我的测试代码,在指定的时间内并未结束线程,线程一直在运行着,请大家看看怎么实现这个功能,谢谢!
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class InterruptedThread { /**
* @param args
*/
public static void main(String[] args) {
final MyThread myTh = new MyThread();
final Timer t = new Timer(200,new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("1 actionPerformed:" );
myTh.interrupt();
}
});
t.setRepeats(false); t.start();
myTh.start();
}}class MyThread extends Thread {
public void run() {
for(int i=0;i<100000000;i++){
System.out.println("MyThread run:" + i);
}
}
}
以下是我的测试代码,在指定的时间内并未结束线程,线程一直在运行着,请大家看看怎么实现这个功能,谢谢!
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class InterruptedThread { /**
* @param args
*/
public static void main(String[] args) {
final MyThread myTh = new MyThread();
final Timer t = new Timer(200,new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("1 actionPerformed:" );
myTh.interrupt();
}
});
t.setRepeats(false); t.start();
myTh.start();
}}class MyThread extends Thread {
public void run() {
for(int i=0;i<100000000;i++){
System.out.println("MyThread run:" + i);
}
}
}
[email protected]
public class TestThread { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
FatherThread father = new FatherThread();
father.start();
}}
父线程:
public class FatherThread extends Thread{
public void run(){
try{
System.out.println("开始监听此代码段,给两秒钟执行时间:");
ListenThread thread = new ListenThread(2*1000,this);//监听2秒
thread.start();
//写死循环进行测试
boolean flag = true;
while(flag){
}
//以下这句是不会打出来的,因为当前的线程被守护线程关闭了
System.out.println("监听完毕,未发现代码执行有问题,所以取消监听器");
thread.cancel();
}catch(Exception e){
e.printStackTrace();
}
}
}守护线程:public class ListenThread extends Thread{
private boolean isCanceled = false;
private FatherThread fatherThread = null;
/**
* 计时器超时时间
*/
private long timeout;
/**
* 构造器
* @param timeout 指定超时的时间
*/
public ListenThread(long timeout,FatherThread father) {
super();
this.fatherThread = father;
this.timeout = timeout;
//设置本线程为守护线程
this.setDaemon(true);
}
/**
* 取消计时
*/
public void cancel()
{
isCanceled = true;
}
/**
* 启动超时计时器
*/
public void run()
{
try {
//log.info("线程开始睡觉:"+timeout+"毫秒。");
System.out.println("父线程状态:"+this.fatherThread.isAlive()+"");
Thread.sleep(timeout);
if(!isCanceled){
//只要是在指定的timeout时间内,被监控的代码段没有执行完,则中止该线程
System.out.println("关闭父线程");
//System.out.println("父线程状态:"+this.fatherThread.isAlive()+"");
//if(this.fatherThread.isAlive()){
//System.out.println("父线程还活着,需要关闭");
this.fatherThread.stop();
//System.out.println("父线程状态:"+this.fatherThread.isAlive()+"");
//}
}else System.out.println("不需要关闭父线程");
} catch (Exception e) {
System.out.println("守护线程异常");
e.printStackTrace();
}
}
}
其中涉及到两个线程,一个是任务线程,一个是监控线程。
首先要明确各个线程的功能,内容。
1.任务线程要具备两个功能,一个功能是执行任务(就是LZ所说的长时间任务);另一个功能应该是终止正在进行的任务。
2.终止正在进行的任务,这个功能,一般是通过在代码中设置标志位来处理的。
设置一个boolean型的变量作为标志位(线程运行是设置为true,结束时设置为false),找出任务的每个原子操作
(一般原子操作的时间会非常短,如果有长时间的原子操作或原子操作有阻塞操作,同时又不允许长时间等待关闭,则该方案不推荐使用),
在执行每个原子操作之前,先判断标志位,如果标志位为false则终止任务(当然,可以同时记录日志)。
3.监控线程,由于LZ的要求是要在某个时间点到达时,再判断并终止任务线程,所以,代码可以上来先sleep到时间点,
然后,在判断任务线程的标志位,如果为true,就设置成false,这样,任务线程,会自动终止。
其次要明确步骤。
1.任务线程在开始任务之前要设置标志位为true,同时创建监控线程(一般会将本身传递给监控线程的构造器)并运行监控线程。
2.任务线程开始执行任务,同时监控线程会进入sleep
3.当监控线程结束sleep后,会判断任务线程是否正在执行(判断标志位),如果为true就将其设置为false。
最后,补充一点,对标志位的更改操作,一般封装在任务线程的某个方法里面,让监控线程去调用。
关于停止父线程的,这个问题,我考虑了很久,stop()在JDK中是不建议使用的,的确存在问题。不知道你使用这个方法的环境如何,是否是考虑到了其他因素对stop()后,对父线程的影响。希望能给出使用stop()是否安全可行的思路