如何扔从java线程检查的异常?(How to throw a checked exception

2019-06-21 11:58发布

嗨,我正在写一个网络应用,在我读了一些自定义的二进制格式的数据包。 而我开始一个后台线程等待传入的数据。 问题是,该编译器不会让我把任何代码投掷(选中)异常转换成run() 它说:

run() in (...).Listener cannot implement run() in java.lang.Runnable; overridden method does not throw java.io.IOException

我想除了杀死线程,并让它在父线程某处捕获。 这是可能实现或做我必须处理线程每一个例外?

Answer 1:

警告:这可能无法满足您的需求,如果你有使用异常机制。

如果我理解正确的话,你实际上并不需要进行检查(您接受的答案这意味着一个未经检查的异常)异常,从而将一个简单的监听器模式是比较合适?

监听器可以住在父线程,而当你已经陷入子线程的检查异常,你可以简单地通知听众。

这意味着你有暴露,这将发生(通过public方法)的一种方式,并能够传递更多信息不是例外允许。 但它确实意味着会有父和子线程之间的耦合(虽然是一个松散的一个)。 这将取决于在你的具体情况,这是否会对在与选中一个包裹检查异常的好处。

这里有一个简单的例子(从另一个答案借用一些代码):

public class ThingRunnable implements Runnable {
    private SomeListenerType listener;
    // assign listener somewhere

    public void run() {
        try {
            while(iHaveMorePackets()) { 
                doStuffWithPacket();
            }
        } catch(Exception e) {
            listener.notifyThatDarnedExceptionHappened(...);
        }
    }
 }

耦合来自于具有为类型的父线程的对象SomeListenerType



Answer 2:

为了能够例外发送到父线程,你可以把你的后台线程处于可赎回 (它允许抛出还检查异常),你再传递到提交的方法有些执行人 。 提交方法将返回一个未来 ,然后您可以用它来获得异常(其GET方法将抛出ExecutionException当它包含了原来的除外)。



Answer 3:

这个答案是基于艾司科Luontola之一,但它提供了一个工作示例。

不同于Runnable接口的run()方法可调用的call()方法可以抛出一些例外。 下面是一个实现的例子:

public class MyTask implements Callable<Integer> {

    private int numerator;
    private int denominator;

    public MyTask(int n, int d) {
        this.numerator = n;
        this.denominator = d;
    }

    @Override
    // The call method may throw an exception
    public Integer call() throws Exception {
        Thread.sleep(1000);
        if (denominator == 0) {
            throw new Exception("cannot devide by zero");
        } else {
            return numerator / denominator;
        }
    }

}

执行器提供了一种机制来运行可调用线程内,以处理任何类型的异常:

public class Main {

    public static void main(String[] args) {

        // Build a task and an executor
        MyTask task = new MyTask(2, 0);
        ExecutorService threadExecutor = Executors.newSingleThreadExecutor();

        try {
            // Start task on another thread
            Future<Integer> futureResult = threadExecutor.submit(task);

            // While task is running you can do asynchronous operations
            System.out.println("Something that doesn't need the tasks result");

            // Now wait until the result is available
            int result = futureResult.get();
            System.out.println("The result is " + result);
        } catch (ExecutionException e) {
            // Handle the exception thrown by the child thread
            if (e.getMessage().contains("cannot devide by zero"))
                System.out.println("error in child thread caused by zero division");
        } catch (InterruptedException e) {
            // This exception is thrown if the child thread is interrupted.
            e.printStackTrace();
        }
    }
}


Answer 4:

我要做的就是赶在线程异常,并将其存储作为了Runnable的成员变量。 此异常然后通过在Runnable的一个getter曝光。 然后我扫描所有的线程从父,看看是否有任何异常,并采取适当的行动。



Answer 5:

线程不能抛出异常的任何其他线程(也不到主线程)。 你不能让继承的run()方法抛出任何checked异常,因为你只能比遗传代码,而不是更多扔少。



Answer 6:

如果你真的当引发异常不能做任何有用的东西,你可以包装在一个RuntimeException的检查异常。

try {
    // stuff
} catch (CheckedException yourCheckedException) {
    throw new RuntimeException("Something to explain what is happening", yourCheckedException);
}


Answer 7:

如果你的线程的代码抛出RuntimeExpection,你并不需要添加的run()抛出异常。

但是,使用此解决方案只有在适当的时候,因为这可能是一个坏的初步实践: http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html

任何RuntimeException的或未经检查的异常可以帮助你。 也许你需要创建自己的RuntimeException



Answer 8:

在你的代码是在某种循环的假设,你会写:

public class ThingRunnable implements Runnable {
  public void run() {
    try {
      while(iHaveMorePackets()) { 
        doStuffWithPacket()
      }
    } catch(Exception e) {
      System.out.println("Runnable terminating with exception" + e );
    }
  }
}

异常将自动中断你出你的循环,并在run()方法的结束,该线程将停止。



Answer 9:

包裹里面一个你的异常RuntimeException ,似乎这样的伎俩。

someMethod() throws IOException
{
    try
    {
        new Thread(() ->
        {
            try
            {
                throw new IOException("a checked exception thrown from within a running thread");
            }
            catch(IOException ex)
            {
                throw new RuntimeException("a wrapper exception", ex); // wrap the checked exception inside an unchecked exception and throw it
            }
        }).start();
    }
    catch(RuntimeException ex) // catch the wrapped exception sent from within the thread
    {
        if(ex.getCause() instanceof IOException)
            throw ex.getCause; // unwrap the checked exception using getCause method and use it however you need
        else
            throw ex;
    }
}


文章来源: How to throw a checked exception from a java thread?