Thread with Lambda expression

T4l0n picture T4l0n · Jul 14, 2015 · Viewed 23.5k times · Source

I have an error at line 42 and 43 : Thread t1=new Thread(()->prod.test()); , Thread t2=new Thread(()->cons.test()); Unhandled exception type InterruptedException . If I try to quickfix it will created the try catch with an catch Exception, it will have the same error and will try to fix it in the same way continuing to surround it with 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());
    }

}

Answer

rgettman picture rgettman · Jul 14, 2015

You have created a functional interface Predicate whose method is declared to throw an InterruptedException, which is a checked exception. However, you call test() in the body of a lambda expression as the parameter to the Thread constructor that takes a Runnable, whose run() method is not declared to throw any checked exceptions. Therefore, because the exception is not caught in the body, a compiler error occurs.

Incidentally, it may be confusing to name your own interface Predicate, because of the built-in functional interface java.util.function.Predicate whose functional method returns a boolean.

Because run() can't throw an Exception, you must catch the exception and handle it. You might log the exception and its stack trace. You might wrap the exception in a RuntimeException. Either way, catching the checked exception will allow the code to compile. Example:

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