2015-07-14 15 views
10

Tôi gặp lỗi tại dòng 42 và 43: Thread t1=new Thread(()->prod.test());, Thread t2=new Thread(()->cons.test());Loại ngoại lệ bị loại trừ InterruptedException. Nếu tôi cố gắng nhanh chóng nó sẽ tạo ra thử bắt với một bắt ngoại lệ bắt, nó sẽ có lỗi tương tự và sẽ cố gắng sửa chữa nó trong cùng một cách tiếp tục bao quanh nó với thử bắt.Chủ đề có biểu thức 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()); 
    } 

} 

Trả lời

10

Bạn đã tạo một giao diện chức năng Predicate có phương pháp được khai báo để ném một InterruptedException, mà là một ngoại lệ kiểm tra. Tuy nhiên, bạn gọi số test() trong phần thân của biểu thức lambda làm tham số cho the Thread constructor that takes a Runnable, có run() method is not declared to throw any checked exceptions. Vì vậy, bởi vì ngoại lệ không bị bắt trong cơ thể, một lỗi trình biên dịch xảy ra.

Ngẫu nhiên, có thể gây nhầm lẫn khi đặt tên cho giao diện của riêng bạn Predicate, vì phương pháp chức năng trả về booleanbuilt-in functional interface java.util.function.Predicate.

run() không thể ném số Exception, bạn phải catch ngoại lệ và xử lý. Bạn có thể đăng nhập ngoại lệ và theo dõi ngăn xếp của nó. Bạn có thể bao gồm ngoại lệ trong một số RuntimeException. Dù bằng cách nào, việc đánh dấu ngoại lệ đã kiểm tra sẽ cho phép mã biên dịch. Ví dụ:

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

Như @rgettman nói, tên Predicate là không hạnh phúc ... Dù sao, bạn có thể tận dụng lợi thế của phương pháp default trong Java:

interface PredicateButPleaseChangeMyName { 

    void test() throws InterruptedException; 

    default void tryTest() { 
     try { 
      this.test(); 
     } catch (InterruptedException e) { 
      // handle e (log or wrap in a RuntimeException) 
     } 
    } 
} 

Sau đó, trong phương pháp chính của bạn, chỉ cần tạo các chủ đề bằng cách gọi phương thức mặc định tryTest():

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