java线程超时时间_Java 时间,时间控制,线程超时小结

Java 时间,时间控制,线程超时小结。

——大牛说了做了什么要记下来,以便日后土鸡。

老师安排对webservice的时间进行监管,意思大概就是超时的webservice给kill掉。Webservice的开发基本和java

project的开发大致相同,可以在java project的基础上做修改搞定。所以先拿java project下手熟悉

java的时间,时间控制,线程超时。

先来看看 java的时间类。

import java.util.Date;

在这个类中主要的作用就是使用实时时间,我基本上把实时时间当做验证程序正确运行的一个验证结果。

System.out.println(new Date());

运行这条语句就可以输出当前时间。

有了这个当前时间我们就像进行时间的计算,

Date date1 = new Date();

try

{

Thread.sleep(2000);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

Date date2 = new Date();

long i = date1.getTime() - date2.getTime();

这样计算出来的i是以毫秒为单位的时间差。

进入第二步,我有一个想法比如说有一个函数,我能允许它运行的时间是一个确定值,当超出这个时间之后我想把它kill掉。这个如何实现。这两天走了不少弯路但也学到不少技术。

弯路:用while循环控制运行时间。经过验证发现这是不行的。比如如下代码

while((new

Date(System.currentTimeMillis())).getTime()-date2.getTime()<=3000)

{

lasting(4000);

}

其中lasting就是一个延迟函数,其实根据语法也可以看出来因为在进入while循环后就直接运行lasting函数直到lasting函数执行完了之后才去检查while的判断条件,当然是不能达到目的的。

所以说为了能够达到目的就需要有一个实时的时钟来检测时间,于是我想到用一个线程来监测实时时间。并且我把需要监测运行时间的方法也用一个线程来运行。这样就出现了一个问题,就是监视时间的线程我们不妨叫做timer,需要同限定运行时间的进程不妨设为lasting进行交互,这是因为至少要在lasting超时的时候把它kill掉。代码如下。

import

java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;

import java.util.Calendar;

import java.util.Timer;

import java.io.IOException;

class lasting extends Thread

{

public int i=0;

public void run()

{

//long i=System.currentTimeMillis();

while(i<=300)

{

i++;

try

{

sleep(70);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

System.out.println("lasting finished");

}

}

class ThreadTimer extends Thread

{

private lasting t;

public int k=0;

public ThreadTimer(lasting tt)

{

t=tt;

}

public void run()

{

while(k<=200)

{

k++;

System.out.println(t.i);

try

{

sleep(30);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

t.stop();

}

}

public class timedo

{

public static void main(String[] args)

{

lasting lastt = new lasting();

Thread timet = new ThreadTimer(lastt);

lastt.start();

timet.start();

}

}

最后可以发现在控制台的输出根本达不到300,lasting就被kill掉了。因为需要在timer线程和lasting线程进行通信交互所以我在timer线程中定义了一个private

lasting t;用来引用lasting,然后调用stop()来停止。

这样虽然可以达到目的,但是个人总是感觉怪怪的特别是用一个线程来控制一个线程,而且java对实时的支持也不是很好。

更进一步来实现对方法或者线程的实时控制。现在我不想再定义一个lasting的引用来完成这项任务,我想在时间到了的时候根据线程的特征找到lasting线程然后把它kill掉。这样就出现了一个问题如何找到特定的线程。

这里我想用线程的名字来判断特定的线程。

import

java.text.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;

import java.util.Calendar;

class simpleThread extends Thread

{

public boolean flag = false;

public Object simpleThread ()

{

try

{

return this.clone();

}

catch (CloneNotSupportedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

return null;

}

public void run()

{

try

{

Thread.sleep(300);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

flag = true;

System.out.println("simpleThread finished");

}

}

public class timercancel

{

public static void main(String[] args)

{

// TODO Auto-generated method stub

simpleThread sthread = new simpleThread();

sthread.setName("zhu");//给线程设置特征,在这里我选择使用一个特定的线程名字。

sthread.start();

int n = Thread.activeCount();

System.out.println(n);

Thread[] threads = new Thread[n];

Thread.enumerate(threads);

for(int i =0 ;i

{

Thread thread = threads[i];

System.out.println(thread.getName());

}

try

{

Thread.sleep(1000);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

if(!sthread.flag)

{

sthread.stop();

System.out.println("kill

thread");//如果线程没有自动完成运行就是被kill掉了。

}

}

}

其实这个例子没有从本质上解决不定义引用的问题,因为我是在main函数中定义了simpleThread这个需要被监测的线程,当然可以再main中操作它。所以我还是不太满意。继续研究发现了timer这个java库。

对于timer的功能性介绍网上有很多文章大家可以参考,我这里不再叙述。我做了一个实验代码如下:

import java.util.Timer;

import java.util.Date;

public class MyTimer

{

public static void main(String[] args)

{

Timer timer = new Timer();

// 在1秒后执行此任务,每次间隔2秒,如果传递一个Data参数,就可以在某个固定的时间执行这个任务.

MyTask mytask = new MyTask();

timer.schedule(mytask, 1000,2000);

System.out.println(new Date());

// 这个是用来停止此任务的,否则就一直循环执行此任务了

try

{

Thread.sleep(10000);

}

catch (InterruptedException e)

{

e.printStackTrace();

}

// 使用这个方法退出任务

mytask.cancel();// 同样cancel不了 正在执行的thread。

timer.cancel();//正在执行的会执行完,cancel后面的。

System.out.println(new Date());

}

static class MyTask extends

java.util.TimerTask

{

@Override

public void run()

{

System.out.println("started!"+(new Date()));

try

{

Thread.sleep(10000);

}

catch (InterruptedException e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("Done !"+(new Date()));

}

}

}

这个实验意思是我的timerTask任务的运行时间是10000毫秒,然后我用timer调度它,这个调度是这样的先延迟一秒钟然后在开始运行,然后每隔2秒又开始一个新的timerTask,然后我在main中等待10000毫秒,然后

mytask.cancel();// 同样cancel不了 正在执行的thread。

timer.cancel();//正在执行的会执行完,cancel后面的。

发现正在执行的thread,不能被cancel掉,它们还是会最后运行完,并且输出结果,但后续的thread被cancel掉了。还有如果当我把task当中的sleep里面的参数改成3000会发现如下输出结果。

Tue Aug 14 16:28:50 CST 2012

started!Tue Aug 14 16:28:51 CST 2012

Done !Tue Aug 14 16:28:54 CST 2012

started!Tue Aug 14 16:28:54 CST 2012

Done !Tue Aug 14 16:28:57 CST 2012

started!Tue Aug 14 16:28:57 CST 2012

Done !Tue Aug 14 16:29:00 CST 2012

started!Tue Aug 14 16:29:00 CST 2012

Tue Aug 14 16:29:00 CST 2012

Done !Tue Aug 14 16:29:03 CST 2012

由此可以发现这个timerTask不是每隔两秒就开始一个新的timerTask

的。而是3秒,timer的调度会等一个task完成后才调用一个新的task。

综上,这样尝试不能解决我的问题,就是在规定时间到了的时候cancel掉task。

现在怎么办?网上查资料后发现了一种叫做守护线程的技术,个人感觉它的技术和我做timer线程和lasting线程的思想非常接近。所谓守护线程就也是把需要运行的方法交给一个线程来运行,然后在这个线程中设置一个定时器timer,timer的作用是在规定的运行时间后开始运行timerTask任务。比如说我想让方法myTest()运行两秒,我就设置一个timer(timerTask,2000),这样tiemr会在2秒后运行timerTask,而timerTask所运行的语句就是kill掉myTest()方法的。用timer来kill线程的思路就是这样。

代码如下:

import java.util.Timer;

import java.util.TimerTask;

import java.util.Date;

public class MyTimer2

{

private String name;

private long timeOut;

private Thread thread;

public MyTimer2(String name, long timeOut)

{

this.name = name;

this.timeOut = timeOut;

}

public void startShutdownTimeout(long

timeOut)

{

new Timer(true).schedule(new TimerTask()

{ // true,表示执行的线程是一个守护线程

@Override

public void run()

{

System.out.println("线程" + name + "超时,执行守护线程 !");

// System.exit(1);

thread.stop();

}

}, timeOut);//timer 在timeout后 调用。不重复执行。

}

public void myTest()

{

thread = new Thread()

{

@Override

public void run()

{

startShutdownTimeout(timeOut); // 该线程受到守护线程的作用

System.out.println(name + "Begin");

try

{

Thread.sleep(200); // 函数要执行至少200毫秒

}

catch (InterruptedException e)

{

e.printStackTrace();

}

System.out.println(name + "Over");

}

};

thread.start();

}

public static void main(String[] args)

{

MyTimer2 m1 = new MyTimer2("1 - ", 100);

MyTimer2 m2 = new MyTimer2("2 - ", 180);

MyTimer2 m3 = new MyTimer2("3 - ", 250);

MyTimer2 m4 = new MyTimer2("4 - ", 320);

m1.myTest();

m2.myTest();

m3.myTest();

m4.myTest();

}

}

运行结果如下:

1 - Begin

3 - Begin

4 - Begin

2 - Begin

线程1 - 超时,执行守护线程 !

线程2 - 超时,执行守护线程 !

4 - Over

3 - Over

感谢网上无偿提供代码的人们,你们才是真正的英雄。好人一生平安。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值