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
Thread with Lambda expression
提问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 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.
您已经创建了一个函数式接口,Predicate
其方法被声明为抛出一个InterruptedException
,这是一个已检查的异常。但是,您test()
将 lambda 表达式的主体作为参数调用到采用 a的Thread
构造函数Runnable
,其run()
方法未声明为抛出任何已检查的异常。因此,由于异常未在主体中捕获,因此会发生编译器错误。
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
.
顺便说一句,命名您自己的 interface 可能会令人困惑Predicate
,因为内置函数式接口java.util.function.Predicate
的函数式方法返回一个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:
因为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 Predicate
is unhappy... Anyways, you could take advantage of default
methods in Java:
正如@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)
}
}
}
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());