java 线程超时中断实现
有一个需求,就是当一个方法执行超时的时候就中断该方法.
java的超时实现,在网上搜到的大部分是:
方法1.
中断线程最好的,最受推荐的方式是,使用共享变量(shared variable)发出信号,告诉线程必须停止正在运行的任务。线程必须周期性的核查这一变量(尤其在冗余操作期间),然后有秩序地中止任务。Listing B描述了这一方式。
Listing B
class Example2 extends Thread {
volatile boolean stop = false;
public static void main( String args[] ) throws Exception {
Example2 thread = new Example2();
System.out.println( "Starting thread..." );
thread.start();
Thread.sleep( 3000 );
System.out.println( "Asking thread to stop..." );
thread.stop = true;
Thread.sleep( 3000 );
System.out.println( "Stopping application..." );
//System.exit( 0 );
}
public void run() {
while ( !stop ) {
System.out.println( "Thread is running..." );
long time = System.currentTimeMillis();
while ( (System.currentTimeMillis()-time < 1000) && (!stop) ) {
}
}
System.out.println( "Thread exiting under request..." );
}
}
另外,httpclient中就提供了这样一个class- timeoutcontroller(位于org.Apache.commons.httpclient.util包内)查看该class的源代码可知其实现细节:
public static void execute(thread task, long timeout) throws timeoutexception {
task.start();
try {
task.join(timeout);
} catch (interruptedexception e) {
/* if somebody interrupts us he knows what he is doing */
}
if (task.isalive()) {
task.interrupt();
throw new timeoutexception();
}
}
其实就是通过join()和interrupt()方法实现这种功能,文档中强调了task的interrupt()方法必须重写(override)
方法2.
用join,就是在主线程里开一个子线程(t),在子线程里去处理超时任务,主线程t.join(3000),3000为要等待的时间(ms),如果子线程没有超时则正常继续执行,如果超时了则中断该子线程t.interrupt();
代码如下:
- public class ThreadTest {
- public static void main(String[] args) {
- CounterThread ct = new CounterThread(5000);
- System.out.println("start...");
- System.out.println("ct start...");
- ct.start();
- System.out.println("ct join...");
- try {
- ct.join(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(ct.isAlive());
- ct.interrupt();
- System.out.println(ct.isAlive());
- System.out.println("the result is " + ct.getResult());
- }
- }
- class CounterThread extends Thread {
- private int time;
- public CounterThread(int time) {
- this.time = time;
- }
- private int result;
- public int getResult() {
- return result;
- }
- public void run() {
- try {
- Thread.sleep(time);
- System.out.println(Thread.currentThread().getName()
- + " is blocked for " + time + "ms");
- } catch (InterruptedException ex) {
- }
- result = 5;
- }
- }
这种方式是可以的,其实还有另外一种方式,就是
- public class TimeoutTest1 {
- public static void main(String[] args) {
- final ExecutorService service = Executors.newFixedThreadPool(1);
- TaskThread taskThread = new TaskThread();
- System.out.println("提交任务...begin");
- Future<Object> taskFuture = service.submit(taskThread);
- System.out.println("提交任务...end");
- try {
- System.out.println("get .... begin");
- Object re = taskFuture.get(1000, TimeUnit.MILLISECONDS);
- System.out.println(re);
- System.out.println("get .... end");
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- } catch (TimeoutException e) {
- System.out.println("超时 取消任务");
- taskFuture.cancel(true);
- System.out.println("超时 取消任务OK");
- }finally{
- System.out.println("关闭服务");
- service.shutdown();
- System.out.println("关闭服务OK");
- }
- }
- }
- class TaskThread implements Callable<Object> {
- public Object call() throws Exception {
- String result = "空结果";
- try {
- System.out.println("任务开始....");
- Thread.sleep(5000);
- result = "正确结果";
- System.out.println("任务结束....");
- } catch (Exception e) {
- System.out.println("Task is interrupted!");
- }
- return result ;
- }
- }