mik*_*1aj 40 java exception thread-exceptions
嘿,我正在写一个网络应用程序,我在其中读取一些自定义二进制格式的数据包.我正在开始一个后台线程来等待传入的数据.问题是,编译器不允许我将任何代码抛出(检查)异常run().它说:
run() in (...).Listener cannot implement run() in java.lang.Runnable; overridden method does not throw java.io.IOException
我希望异常杀死该线程,并让它在父线程的某处被捕获.这是可能实现还是我必须处理线程内的每个异常?
Esk*_*ola 48
为了能够将异常发送到父线程,您可以将后台线程放在Callable中(它允许抛出也检查过的异常),然后将其传递给某些Executor的submit方法.submit方法将返回一个Future,然后您可以使用它来获取异常(它的get方法将抛出包含原始异常的ExecutionException).
Gru*_*eck 38
警告:如果必须使用异常机制,这可能无法满足您的需求.
如果我理解正确,你实际上并不需要检查异常(你接受了建议未经检查的异常的答案)那么一个简单的监听器模式会更合适吗?
侦听器可以驻留在父线程中,当您在子线程中捕获到已检查的异常时,您可以简单地通知侦听器.
这意味着您有一种方法可以揭示这种情况(通过公共方法),并且能够传递比异常允许的更多信息.但它确实意味着父线程和子线程之间将存在耦合(尽管是松散的).这取决于您的具体情况,这是否有利于使用未经检查的异常包装已检查的异常.
这是一个简单的例子(从另一个答案借来的一些代码):
public class ThingRunnable implements Runnable {
private SomeListenerType listener;
// assign listener somewhere
public void run() {
try {
while(iHaveMorePackets()) {
doStuffWithPacket();
}
} catch(Exception e) {
listener.notifyThatDarnedExceptionHappened(...);
}
}
}
Run Code Online (Sandbox Code Playgroud)
耦合来自父线程中的对象必须是类型SomeListenerType.
a.b*_*b.d 33
这个答案基于Esko Luontola,但它提供了一个有效的例子.
与Runnable接口的run()方法不同,Callable的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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
Executor提供了一种在线程内运行Callable并处理任何类型异常的机制:
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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我所做的是捕获线程中的异常并将其存储为Runnable的成员变量.然后通过Runnable上的getter公开此异常.然后我扫描父项中的所有线程以查看是否有异常,并采取适当的操作.
如果在引发异常时您确实无法做任何有用的事情,则可以将已检查的异常包装在 RuntimeException 中。
try {
// stuff
} catch (CheckedException yourCheckedException) {
throw new RuntimeException("Something to explain what is happening", yourCheckedException);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
69603 次 |
| 最近记录: |