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());
}
}
チェックされた例外であるPredicate
をスローするようにメソッドが宣言されている関数インターフェイスInterruptedException
を作成しました。ただし、ラムダ式の本体でtest()
を Thread
を引数とする Runnable
コンストラクターへのパラメーターとして呼び出し、その--- [run()
メソッドをチェックされた例外をスローするように宣言されていません 。したがって、例外が本体でキャッチされないため、コンパイラエラーが発生します。
ちなみに、- 組み込みの関数型インターフェイス_Java.util.function.Predicate
_ の関数メソッドが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);
}
});
_
引数なしで単一のメソッドのみを実行する場合は、ラムダをメソッド参照で置き換えることができます。
例えば:
Thread t = new Thread(() -> {
foo();
});
より簡潔に表現することができます
Thread t = new Thread(this::foo);
@rgettmanが言うように、Predicate
という名前は不幸です...とにかく、Javaのdefault
メソッドを利用できます。
_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());
_