论坛首页 入门技术论坛

不可能完成任务?Thread的超时自动终止

浏览 29294 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (1) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-04-30  
楼上正解。
0 请登录后投票
   发表时间:2009-04-30   最后修改:2009-04-30
ispring 写道
kowen 写道
ispring 写道
看看 Http-Client 中怎么处理的吧,对于兼容1.4中建立Socket超时问题的解决方案:

/**
     * Executes <code>task</code>. Waits for <code>timeout</code>
     * milliseconds for the task to end and returns. If the task does not return
     * in time, the thread is interrupted and an Exception is thrown.
     * The caller should override the Thread.interrupt() method to something that
     * quickly makes the thread die or use Thread.isInterrupted().
     * @param task The thread to execute
     * @param timeout The timeout in milliseconds. 0 means to wait forever.
     * @throws TimeoutException if the timeout passes and the thread does not return.
     */
    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();
        }
    }


我写了一个ThreadA,用以上方法运行结果还是不行
public class ThreadA extends Thread {
	
	private long startTime;

	public ThreadA(String name) {
		super(name);
	}

	public void run() {
		this.startTime = System.currentTimeMillis();
		int i = 0;
		while (i++<20) {
			try {
				this.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(this.getName()+":"+i);
		}

		System.out.println(this.getName()+"已完成");

	}
}


结果:
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at thread.ThreadA.run(ThreadA.java:22)
Exception in thread "main" java.util.concurrent.TimeoutException
at thread.Test.execute(Test.java:28)
a:1
at thread.Test.main(Test.java:16)
a:2
a:3
a:4
a:5
a:6
a:7
a:8
a:9
a:10
a:11
a:12
a:13
a:14
a:15
a:16
a:17
a:18
a:19
a:20
a已完成

说明Thread还是运行完成了,没有被终止,这种方式只能通知客户端超时,服务端还是继续运行



把你的 main 方法帖出来吧


main如下所示

public class Test {
    public static void main(String args[]) throws TimeoutException{
         ThreadA a = new ThreadA("a");
         Test.execute(a, 10);
    }
	
    public static void execute(Thread task, long timeout) throws TimeoutException {   
        task.start();   
        try {   
            task.join(timeout);   
        } catch (InterruptedException e) {   
            System.out.println("ddd");
        }   
        if (task.isAlive()) {   
            task.interrupt();   
            throw new TimeoutException();   
        }   
    }  
}

0 请登录后投票
   发表时间:2009-04-30  
fight_bird 写道
设计影子线程可以解决:A线程+A影子线程,同时启动,后者负责A线程的生存周期,并在结束A线程的同时结束自己。

这个任务很久之前设计过,是一个高负载的业务Log,为了应付瞬时可能过100的并发log请求,实践证明是完全可以完成的。

楼主先考虑一下我这个思路,不行我再去找以前的源代码。


考虑过,但是影子线程通过什么方法控制A线程的生命周期呢?如果不用Stop,还是没办法终止
0 请登录后投票
   发表时间:2009-04-30   最后修改:2009-04-30
java.lang.Object 写道
除非你调用Thread的stop方法,否则你不可能精确地做到超时的线程退出,因为线程在执行一个方法的时候,这个方法可能很耗时,所以用设置标量的方法是不可行的,设置标量的方法可以用在线程是循环执行小的不耗时的方法的时候。
而每次执行前检查一下是否要退出线程也是不可靠的,就是因为上述的原因,一个方法可能会执行很长时间。

此题要想解决,只能把大的耗时的任务分解为小的循环式的来执行的,这样可以用一个boolean值来控制循环是否退出从而结束某个线程。

stop方法之所以过时,是因为1,它相当于进程里面的杀死进程,用这种方法来强行杀死线程会使得很多关键的数据或者操作得不到完整性的保证。2,它不会释放对象锁。


正解,循环的任务通过设置boolean是可以实现条件退出的。

如果不用stop,看来是没有办法停止线程的~

换一个思路
private void run(){
      try{
            启动一个Timer,定时报一个TimeOutException 
            费时很长的业务逻辑
      }catch(TimeOutException e)
      {
          System.out.println("超时了!");
      }finally{
          System.out.println("释放资源退出!");
      }
}


这个可行么?可是java.util.TimerTask的run方法不抛出异常
0 请登录后投票
   发表时间:2009-04-30  
beetle框架是可以实现线程超时释放的事件
有兴趣可以参考一下我的博文《线程子程序及其执行方式》
0 请登录后投票
   发表时间:2009-04-30  
什么是 影子线程....能大概说下吗...谢谢
0 请登录后投票
   发表时间:2009-04-30   最后修改:2009-04-30
binlaniua 写道
什么是 影子线程....能大概说下吗...谢谢

daemon thread
0 请登录后投票
   发表时间:2009-04-30  
java.lang.Object 写道
除非你调用Thread的stop方法,否则你不可能精确地做到超时的线程退出,因为线程在执行一个方法的时候,这个方法可能很耗时,所以用设置标量的方法是不可行的,设置标量的方法可以用在线程是循环执行小的不耗时的方法的时候。
而每次执行前检查一下是否要退出线程也是不可靠的,就是因为上述的原因,一个方法可能会执行很长时间。

此题要想解决,只能把大的耗时的任务分解为小的循环式的来执行的,这样可以用一个boolean值来控制循环是否退出从而结束某个线程。

stop方法之所以过时,是因为1,它相当于进程里面的杀死进程,用这种方法来强行杀死线程会使得很多关键的数据或者操作得不到完整性的保证。2,它不会释放对象锁。


synchronized的锁肯定会释放的,试试就知道了
官方解释也是可能会导致数据不一致

真正的耗时任务还能分解,
但那些涉及网络的 比如 client 跟server rmi ,server再用WS通过adapt跟硬件打交道,
如果硬件或者adapt,server某个环节被阻塞 client调用线程就会被阻塞
依赖的东西太多 client缺乏有效的控制能力
0 请登录后投票
   发表时间:2009-05-02   最后修改:2009-05-02
 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是等待线程结束,timeout设置等待时间,如果超时,则线程进入调度。查了下JDK对wait(long)的注释是:

引用

The specified amount of real time has elapsed, more or less.The thread <var>T</var> is then removed from the wait set for this
object and re-enabled for thread scheduling.


interrupt();官方有这样一段解释:

引用
* <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown.


弱弱的问句“影子线程”不用interrupt()吗?

希望对楼主有所帮助!
0 请登录后投票
   发表时间:2009-05-04  
在多进程的年代,我们可以通过直接kill xxx来结束它,把这个思路放入Thread也无可厚非。
但无论如何,还是要尽量保障Theard的内的代码运行的“可介入”性。任意点可插入if (stopped)代码,而每个检查周期最长运行间隔永远不会太长。否则神仙也不能安全的拯救你。
强制性的stop或interrupt,无异于通过“拔掉电源插头”的方式来停止程序的运行,然而这种绝对有效的方式是绝对不安全的。

0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics