2013-07-23 19 views
9

Tôi xác định đối tượng tĩnh chung là khóa đồng bộ hóa.Android java.lang.IllegalMonitorStateException: đối tượng không bị khóa theo chuỗi trước khi chờ()

public static Object ConfirmationSynObj = new Object(); 

Chức năng sau đây là những gì tôi đã viết, nhưng nó ném một IllegalMonitorStateException.

 synchronized (Config.ConfirmationSynObj) { 
      new Thread(new Runnable() { 

       @Override 
       public void run() { 
        //this is a http request 
        appSignInfo = getAPKSignature(context, pkinfo.packageName); 
        Config.ConfirmationSynObj.notify(); 
       } 
      }).start(); 
      try { 
       Config.ConfirmationSynObj.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

      if (appSignInfo == null) { 
       return ret; 
      } 
     } 

Có ai biết cách khóa đối tượng hoặc chức năng để ngăn không cho đồng thời không?

+5

Vui lòng thực hiện theo các quy ước đặt tên Java. –

Trả lời

9

Một thay thế chung cho wait/notifyCountDownLatch . (Từ java.util.concurrent cũng như loại hoạt động nghịch đảo của Semaphore - xem câu trả lời của Tom)

Bạn khởi tạo số bước cần thiết, chủ đề đã hoàn thành đếm ngược và một số nơi khác chờ đếm ngược để đạt 0.

void doFoo() { 
    final CountDownLatch latch = new CountDownLatch(1); 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 
      //this is a http request 
      appSignInfo = getAPKSignature(context, pkinfo.packageName); 
      latch.countDown(); 
     } 
    }).start(); 
    try { 
     latch.await(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    if (appSignInfo == null) { 
     return ret; 
    } 
} 

Nhưng đoạn code bạn đã viết có thể được đơn giản hóa để

void doFoo() { 
    return getAPKSignature(context, pkinfo.packageName); 
} 

bạn bắt đầu một thread thứ hai để làm điều gì đó và tất cả các bạn làm trong thời gian đó là chờ đợi. Nếu không có gì để làm trong khi nhiệm vụ đó đang chạy không tạo ra một chuỗi phụ. Kết quả là như nhau.

Nếu bạn cố gắng thực hiện yêu cầu HTTP bên ngoài chuỗi giao diện người dùng vì bạn nhận được điều đó NetworkOnMainThreadExcpeption, bạn phải làm điều đó khác đi. Mặc dù Android sẽ không phát hiện mã của bạn là mã chặn thời gian dài mà nó vẫn tồn tại. Sử dụng AsyncTask chẳng hạn.

2

Bạn có thể đang tạo và bắt đầu chuỗi trong khối được đồng bộ hóa, nhưng khi chuỗi đến Config.ConfirmationSynObj.notify(); bạn sẽ nhận thấy rằng không có đồng bộ hóa.

Bạn sẽ cần phải thêm khối được đồng bộ hóa bên trong run().

5

@Kayaman nói đúng, theo như tôi có thể nói, tuy nhiên nếu tôi có thể gợi ý: java.util.concurrent có thể giúp bạn tiết kiệm rất nhiều thời gian!

Điều tôi muốn sử dụng là semaphore.

Từ tài liệu: "Mỗi khối có được() nếu cần thiết cho đến khi có giấy phép và sau đó lấy nó.".

Nhưng cũng có các lựa chọn khác - Tôi khuyên bạn nên sử dụng điều này nếu có thể, vì bạn nên tránh nhiều hố rơi như trong trường hợp của bạn.

 Semaphore semaphore = new Semaphore(0); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       //this is a http request 
       appSignInfo = getAPKSignature(context, pkinfo.packageName); 
       semaphore.release(); 
      } 
     }).start(); 
     try { 
      semaphore.acquire(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
2
new Thread(new Runnable() { 

      @Override 
      public void run() { 

Trên chủ đề không được sở hữu khóa trên ConfirmationSynObj đối tượng do đó ném IllegalMonitorStateException

Sử dụng một khối đồng bộ hơn trong run phương pháp

  @Override 
      public void run() { 
      synchronized (Config.ConfirmationSynObj) { 
       //this is a http request 
       appSignInfo = getAPKSignature(context, pkinfo.packageName); 
       Config.ConfirmationSynObj.notify(); 
       } 
      }