J'ai une erreur aux lignes 42 et 43: Thread t1=new Thread(()->prod.test());
, Thread t2=new Thread(()->cons.test());
Type d'exception non gérée InterruptedException . Si j'essaie de procéder à la correction rapide, il créera la tentative try avec un catch Exception , le même message d'erreur s'affichera et il tentera de la réparer de la même manière en continuant de l'entourer avec 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());
}
}
Vous avez créé une interface fonctionnelle Predicate
dont la méthode est déclarée pour lancer une InterruptedException
, qui est une exception vérifiée. Cependant, vous appelez test()
dans le corps d'une expression lambda en tant que paramètre de le constructeur Thread
qui prend un Runnable
, dont la méthode run()
n'est pas déclarée pour lancer les exceptions vérifiées . Par conséquent, étant donné que l'exception n'est pas interceptée dans le corps, une erreur du compilateur se produit.
Incidemment, il peut être déroutant de nommer votre propre interface Predicate
, en raison de l'interface fonctionnelle intégrée Java.util.function.Predicate
/ dont la méthode fonctionnelle retourne une boolean
.
Comme run()
ne peut pas lancer Exception
, vous devez catch
l'exception et la gérer. Vous pouvez enregistrer l'exception et sa trace de pile. Vous pouvez envelopper l'exception dans une RuntimeException
. Dans les deux cas, attraper l'exception vérifiée permettra au code de se compiler. Exemple:
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);
}
});
Comme @rgettman le dit, le nom Predicate
est malheureux ... Quoi qu'il en soit, vous pouvez tirer parti des méthodes default
en Java:
interface PredicateButPleaseChangeMyName {
void test() throws InterruptedException;
default void tryTest() {
try {
this.test();
} catch (InterruptedException e) {
// handle e (log or wrap in a RuntimeException)
}
}
}
Ensuite, dans votre méthode principale, créez simplement les threads en appelant la méthode par défaut tryTest()
:
Thread t1 = new Thread(() -> prod.tryTest());
Thread t2 = new Thread(() -> cons.tryTest());
Si vous envisagez d'exécuter une seule méthode sans aucun argument, vous pouvez remplacer le lambda par une référence de méthode.
Par exemple:
Thread t = new Thread(() -> {
foo();
});
peut être plus succinctement exprimé comme
Thread t = new Thread(this::foo);