具有Lambda表达式的线程

我在第42和43行有一个错误: Thread t1=new Thread(()->prod.test());Thread t2=new Thread(()->cons.test()); 未处理的exception类型InterruptedException 。 如果我尝试quickfix它将创建带有捕获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  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()); } } 

您已经创建了一个function接口Predicate其方法被声明为抛出InterruptedException ,这是一个经过检查的exception。 但是,在lambda表达式的主体中调用test()作为Thread构造函数的参数, 该构造函数接受Runnable ,其run()方法未声明为抛出任何已检查的exception 。 因此,由于exception未在正文中捕获,因此会发生编译器错误。

顺便说一下,由于内置的函数接口java.util.function.Predicate其函数方法返回一个boolean ,因此命名自己的接口Predicate可能会令人困惑。

因为run()不能抛出Exception ,所以必须catchexception并处理它。 您可以记录exception及其堆栈跟踪。 您可以在RuntimeException包装exception。 无论哪种方式,捕获已检查的exception将允许代码编译。 例:

 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); } }); 

正如@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());