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