2015-07-14 6 views
10

Ho un errore nella riga 42 e 43: Thread t1=new Thread(()->prod.test());, Thread t2=new Thread(()->cons.test());Tipo di eccezione non gestito InterruptedException. Se provo a quickfix, verrà creato il try catch con una cattura Exception, avrà lo stesso errore e proverà a risolverlo nello stesso modo continuando a circondarlo con try catch.Thread con espressione Lambda

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()); 
    } 

} 

risposta

10

È stata creata un'interfaccia funzionale Predicate il cui metodo è dichiarato per lanciare un InterruptedException, che è un'eccezione controllata. Tuttavia, si chiama test() nel corpo di un'espressione lambda come parametro su the Thread constructor that takes a Runnable, di cui run() method is not declared to throw any checked exceptions. Pertanto, poiché l'eccezione non viene rilevata nel corpo, si verifica un errore del compilatore.

Per inciso, può essere fonte di confusione per citarne la propria interfaccia Predicate, a causa della built-in functional interface java.util.function.Predicate cui metodo funzionale restituisce un boolean.

Perché run() non può lanciare un Exception, è necessario catch l'eccezione e gestirlo. È possibile registrare l'eccezione e la sua traccia di stack. È possibile avvolgere l'eccezione in un RuntimeException. In entrambi i casi, la cattura dell'eccezione controllata consentirà la compilazione del codice. Esempio:

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); 
    } 
}); 
3

Come @rgettman dice il nome Predicate è infelice ... In ogni modo, è possibile usufruire di default metodi 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) 
     } 
    } 
} 

Poi, nel metodo principale, è sufficiente creare i thread chiamando il metodo predefinito tryTest():

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