/**
 * 本线程设置了一个超时时间
 * 该线程开始运行后,经过指定超时时间,
 * 该线呈会抛出一个未检查异常通知调用该线呈的程序超时
 * 在超时结束前可以调用该类的cancel方法取消计时
 * @author solonote
 */
public class TimeoutThread extends Thread
{    /**
     * 计时器超时时间
     */
    private long timeout;    /**
     * 计时是否被取消
     */
    private boolean isCanceled = false;    /**
     * 当计时器超时时抛出的异常
     */
    private CaiException timeoutException;    /**
     * 构造器
     * @param timeout 指定超时的时间
     */
    public TimeoutThread(long timeout, CaiException timeoutErr)
    {
        super();
        this.timeout = timeout;
        this.timeoutException = timeoutErr;
        //设置本线程为守护线程
        //this.setDaemon(true);
    }    /**
     * 取消计时
     */
    public void cancel()
    {
        isCanceled = true;
        System.out.println("cancel ing");
    }    /**
     * 启动超时计时器
     * @throws TimeoutException 
     */
    public void run() throws CaiException
    {
        try
        {
            Thread.sleep(timeout);
            if (!isCanceled)
            {
                System.out.println("throw timeoutException!");
                throw timeoutException;
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}public class CaiException extends RuntimeException
{    /**
     * 序列化号
     */
    private static final long serialVersionUID = -8078853655388692688L;    public CaiException(String errMessage)
    {
        super(errMessage);
    }
}
我在下面的方法里使用这个超时控制线程:public class TestTimeOut
{
    public static void main(String[] args)
    {
        //      初始化超时类
        TimeoutThread t = new TimeoutThread(100, new CaiException("超时"));
        try
        {
            t.start();
            //要检测超时的程序段
            print();
            t.cancel();
        }
        catch (CaiException e)
        {
            //...对超时的处理...
            stop();
        }    }    private static void print()
    {
        while (true)
        {
            System.out.println("printing....");
        }
        
    }    private static void stop()
    {
        System.out.println("stop***********************************");
    }
}结果是根本没stop,TimeoutThread 抛出了异常,但是没有被捕获,为啥没被捕获呢,难道不是一个线程就捕获不了吗

解决方案 »

  1.   

    private boolean isCanceled = false;改成private volatile boolean isCanceled = false;
      

  2.   

    而且你这个线程写的有问题  t.cancel();你的timeout时间设的那么短,可能都已经跑完了,你cancel做什么,看不出来效果弄长点
      

  3.   

    print();你这个是主线程里的,一个while(true)不停的打,啥意思?
      

  4.   

    跑了一下代码才发现你的
    run throws CaiException很有创意你把throws CaiException删掉,看看为什么下面throw一个,上面不用throw,catch也没有catch到,编译器也不报错,就应该知道原因了
      

  5.   


    /**
     * 本线程设置了一个超时时间
     * 该线程开始运行后,经过指定超时时间,
     * 该线呈会抛出一个未检查异常通知调用该线呈的程序超时
     * 在超时结束前可以调用该类的cancel方法取消计时
     * @author solonote
     */
    public class TimeoutThread extends Thread
    {    /**
         * 计时器超时时间
         */
        private long timeout;    /**
         * 计时是否被取消
         */
        private boolean isCanceled = false;    /**
         * 当计时器超时时抛出的异常
         */
        private CaiException timeoutException;    /**
         * 构造器
         * @param timeout 指定超时的时间
         */
        public TimeoutThread(long timeout, CaiException timeoutErr)
        {
            super();
            this.timeout = timeout;
            this.timeoutException = timeoutErr;
            //设置本线程为守护线程
            //this.setDaemon(true);
        }    /**
         * 取消计时
         */
        public void cancel()
        {
            isCanceled = true;
            System.out.println("cancel ing");
        }    /**
         * 启动超时计时器
         * @throws TimeoutException 
         */
        public void run()//修改了
        {
            try
            {
                Thread.sleep(timeout);
                if (!isCanceled)
                {
                    System.out.println("throw timeoutException!");
                    throw timeoutException;
                }
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
    }
    异常不能捕获到的,因为start()方法不会抛那个异常的,呵呵
      

  6.   

    你若想一个线程去停另一个线程,据说是不行的,除了过时的stop这个问题我以前问过
      

  7.   

    楼主的这个要求可以用timer加timertask的组合来实现。下面是我改写的代码,供楼主参考:public class TestTimeOut { private static AtomicBoolean isTimeout = new AtomicBoolean(false); public static void main(String[] args) { Timer timer = new Timer();
    TimeoutTask task = new TimeoutTask(isTimeout);
    timer.schedule(task, 100);
    print();
    timer.cancel(); } private static void print() {
    while (!isTimeout.get()) {
    System.out.println("printing....");
    } }
    }public class TimeoutTask extends TimerTask {

    private AtomicBoolean isTimeout;

    public TimeoutTask(AtomicBoolean isTimeout) {
    this.isTimeout = isTimeout;
    } public void run() {
    while(!this.isTimeout.compareAndSet(false, true));
    }}
      

  8.   

    首先说一下线程调用的异常栈,异常是沿异常栈向上传的,但启动一个线程时,它有自己的栈帖,也就是说有自己的异常栈,导致并不是所有异常都能捕获,这也就是为什么run方法没有throws的原因,这种情况下,采用异常回调是比较好的方案。也就是采用的事件通知机制。详细可以看看ExceptionListener.