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());
}
}
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);
}
});
As @rgettman says, the name Predicate
is unhappy... Anyways, you could take advantage of default
methods in 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:
Thread t1 = new Thread(() -> prod.tryTest());
Thread t2 = new Thread(() -> cons.tryTest());
If you intend on running a single method only with no arguments you can replace the lambda with a method reference.
For instance:
Thread t = new Thread(() -> {
foo();
});
can be more succinctly expressed as
Thread t = new Thread(this::foo);
来源:https://stackoverflow.com/questions/31416784/thread-with-lambda-expression