java 带有 Lambda 表达式的线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31416784/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 18:35:16  来源:igfitidea点击:

Thread with Lambda expression

javamultithreadinglambdainterrupted-exception

提问by T4l0n

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.

我在线路42和43的误差:Thread t1=new Thread(()->prod.test());Thread t2=new Thread(()->cons.test());未处理的异常类型InterruptedException的。如果我尝试快速修复,它将创建带有 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());
    }

}

回答by rgettman

You have created a functional interface Predicatewhose 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 Threadconstructor 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.

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

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

顺便说一句,命名您自己的 interface 可能会令人困惑Predicate,因为内置函数式接口java.util.function.Predicate的函数式方法返回一个boolean.

Because run()can't throw an Exception, you must catchthe 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:

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

回答by MeetTitan

If you intend on running a single method only with no arguments you can replace the lambda with a method reference.

如果你打算只运行一个没有参数的方法,你可以用方法引用替换 lambda。

For instance:

例如:

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

can be more succinctly expressed as

可以更简洁地表示为

Thread t = new Thread(this::foo);

回答by Federico Peralta Schaffner

As @rgettman says, the name Predicateis unhappy... Anyways, you could take advantage of defaultmethods in Java:

正如@rgettman 所说,这个名字Predicate令人不快……无论如何,您可以利用defaultJava 中的方法:

interface PredicateButPleaseChangeMyName {

    void test() throws InterruptedException;

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

Then, in your main method, simply create the threads by calling the default tryTest()method:

然后,在您的 main 方法中,只需通过调用默认tryTest()方法来创建线程:

Thread t1 = new Thread(() -> prod.tryTest());
Thread t2 = new Thread(() -> cons.tryTest());