具有Lambda表达式的线程

时间:2015-07-14 20:35:49

标签: java multithreading lambda interrupted-exception

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

}

3 个答案:

答案 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);