第42行和第43行出错:Thread t1=new Thread(()->prod.test());
,Thread t2=new Thread(()->cons.test());
未处理的异常类型InterruptedException 。如果我尝试quickfix它会创建带有catch Exception 的try catch,它会有同样的错误,并会尝试以同样的方式修复它,继续用try catch包围它。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
interface Predicate {
public void test() throws InterruptedException;
}
class MyClass {
int num = 0;
Lock lock = new ReentrantLock();
public void produce() throws InterruptedException {
lock.lock();
for (int i = 0; i < 1000; i++) {
num++;
Thread.sleep(1);
}
lock.unlock();
}
public void consume() throws InterruptedException {
lock.lock();
for (int i = 0; i < 1000; i++) {
num--;
Thread.sleep(1);
}
lock.unlock();
}
public int getNum() {
return num;
}
}
public class Main00 {
public static void main(String[] args) throws InterruptedException {
MyClass c = new MyClass();
Predicate prod = c::produce;
Predicate cons = c::consume;
Thread t1 = new Thread(() -> prod.test());
Thread t2 = new Thread(() -> cons.test());
long start = System.currentTimeMillis();
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
System.out.println("time taken " + (end - start) + " num = "
+ c.getNum());
}
}
答案 0 :(得分:14)
您已经创建了一个功能接口Predicate
,其方法被声明为抛出InterruptedException
,这是一个经过检查的异常。但是,您在lambda表达式的主体中调用test()
作为the Thread
constructor that takes a Runnable
的参数,其run()
method is not declared to throw any checked exceptions。因此,由于异常未在正文中捕获,因此会发生编译器错误。
顺便说一下,由于built-in functional interface java.util.function.Predicate
的函数方法返回Predicate
,因此命名您自己的界面boolean
可能会造成混淆。
由于run()
无法抛出Exception
,因此您必须catch
异常并处理它。您可以记录异常及其堆栈跟踪。您可以将异常包装在RuntimeException
中。无论哪种方式,捕获已检查的异常将允许代码编译。例如:
Thread t1 = new Thread(() -> {
try {
prod.test();
} catch (InterruptedException e) {
// handle: log or throw in a wrapped RuntimeException
throw new RuntimeException("InterruptedException caught in lambda", e);
}
});
答案 1 :(得分:3)
正如@rgettman所说,名称Predicate
不满意......无论如何,你可以利用Java中的default
方法:
interface PredicateButPleaseChangeMyName {
void test() throws InterruptedException;
default void tryTest() {
try {
this.test();
} catch (InterruptedException e) {
// handle e (log or wrap in a RuntimeException)
}
}
}
然后,在main方法中,只需通过调用默认的tryTest()
方法创建线程:
Thread t1 = new Thread(() -> prod.tryTest());
Thread t2 = new Thread(() -> cons.tryTest());
答案 2 :(得分:0)
如果您打算只运行一个不带参数的方法,则可以将lambda替换为方法引用。
例如:
Thread t = new Thread(() -> {
foo();
});
可以更简洁地表示为
Thread t = new Thread(this::foo);