Поток с лямбда-выражением

У меня ошибка в строках 42 и 43: Thread t1=new Thread(()->prod.test());, Thread t2=new Thread(()->cons.test()); Необработанный тип исключения InterruptedException. Если я попытаюсь быстро исправить, он создаст try catch с Exception, у него будет та же ошибка, и он попытается исправить ее таким же образом, продолжая окружать его 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());
    }

}

person T4l0n    schedule 14.07.2015    source источник


Ответы (3)


Вы создали функциональный интерфейс Predicate, метод которого объявлен для выдачи InterruptedException, что является проверенным исключением. Однако вы вызываете test() в теле лямбда-выражения в качестве параметра конструктор Thread, который принимает Runnable, чей метод run() не объявлен для выдачи проверенных исключений. Поэтому, поскольку исключение не перехватывается в теле, возникает ошибка компилятора.

Кстати, название вашего собственного интерфейса Predicate может сбивать с толку из-за встроенный функциональный интерфейс java.util.function.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);
    }
});
person rgettman    schedule 14.07.2015
comment
Исключение «java.lang.InterruptedException» никогда не возникает в соответствующем блоке try. - person ShadowGames; 04.11.2020
comment
@ShadowGames Это конкретное определение Predicate объявляет test броском InterruptedException, поэтому его можно бросить и его нужно поймать. - person rgettman; 05.11.2020

Если вы собираетесь запускать только один метод без аргументов, вы можете заменить лямбду ссылкой на метод.

Например:

Thread t = new Thread(() -> {
        foo();
    });

можно более кратко выразить как

Thread t = new Thread(this::foo);
person MeetTitan    schedule 12.01.2019

Как говорит @rgettman, имя Predicate недовольно... В любом случае, вы можете воспользоваться преимуществами методов default в Java:

interface PredicateButPleaseChangeMyName {

    void test() throws InterruptedException;

    default void tryTest() {
       try {
          this.test();
       } catch (InterruptedException e) {
          // handle e (log or wrap in a RuntimeException)
       }
    }
}

Затем в вашем основном методе просто создайте потоки, вызвав метод tryTest() по умолчанию:

Thread t1 = new Thread(() -> prod.tryTest());
Thread t2 = new Thread(() -> cons.tryTest());
person fps    schedule 14.07.2015