2013-05-08 5 views
5

Hiện tại, một sự kiện quan trọng được tạo trong GUI sau đó được truyền qua một số lớp và được cấp cho một lớp đang chạy trong một chuỗi riêng biệt. Chủ đề đang đợi một sự kiện quan trọng và khi một người nhận được một biến từ chuỗi tiếp theo lên lớp bị thay đổi (xem sơ đồ). Tuy nhiên trong quá trình gỡ lỗi biến không thay đổi.Biến truy cập từ một lớp khác từ một chủ đề

Lớp mà chuỗi đang truy cập là tất nhiên trong chuỗi riêng của nó vì nó đang được gọi từ GUI đã khiến tôi nghĩ rằng đây là vấn đề với đồng thời.

Có cách nào để giải quyết điều này có lẽ bằng cách sử dụng số nguyên nguyên tử hoặc khóa không? Tôi đã nhìn thấy một vài ví dụ bằng cách sử dụng các chức năng đồng bộ tuy nhiên tôi không thể làm cho họ làm việc vì họ không giải thích các yêu cầu của các lớp học. (theo đó tôi có nghĩa là họ cung cấp cho bạn mã để thực hiện đồng bộ hóa nhưng họ không giải thích cách tạo một lớp "đồng bộ").

Diagram of class structure Đây là mã từ Chủ đề trong lớp E, như bạn có thể tham chiếu đối tượng của chủ đề được thiết lập từ lớp trên mà nhận được một tài liệu tham khảo của hạng A từ lớp trên, vv

private Processor processor; 

    public void run() { 
     while (true) { 
      if (keyevent != null) { 


       keyevent = null; 
       processor.I = 4; 
      } 
     } 
    } 

    public void SetProcessor(Processor processor) { 
     this.processor = processor; 
    } 

Mở rộng trên nhận xét gỡ lỗi. Trong quá trình gỡ lỗi nếu tôi chỉ gỡ lỗi các chủ đề trong lớp E và bước qua nó các chức năng mã tốt và bộ vi xử lý.Tôi nhận được giá trị của bốn. Tuy nhiên khi tôi không gỡ lỗi mà thread không có gì xảy ra trong bộ xử lý đó là lý do tại sao tôi nghĩ rằng nó có thể là một vấn đề đồng thời.

Thực hiện biến thể mà tôi đang truy cập trong Lớp B và Số nguyên nguyên tử, cũng đã thực hiện một số chức năng được sử dụng đồng bộ hóa. chức năng vẫn dosent bên ngoài môi trường gỡ lỗi :(

Mã trong Class B gọi từ Class E

public void SetI(int value){//also tried using synchronized as well 
     I.set(value); 
    } 

Các KeyEvent được tạo ra trong lớp GUI bởi một keyListener (mà cháy whenver một phím được nhấn). Các Đối tượng KeyEvent sau đó được truyền cho lớp E thông qua một số hàm "nhỏ giọt" mà chỉ cần chuyển nó vào lớp tiếp theo, do đó GUI gọi processor.setKeyevent (e), sau đó bộ xử lý gọi bus.setKeyevent (e) và như vậy cho đến khi thuộc tính KeyEvent được đặt trong Class E.

Khi khởi tạo hệ thống, chuỗi trong lớp E được bắt đầu, là liên tục kiểm tra giá trị của thuộc tính Keyevent, khi KeyEvent không rỗng, tức là nó đã được chuyển từ GUI (qua mọi thứ khác) Class E sau đó đặt giá trị của một thuộc tính số nguyên trong lớp B.

Điều gì đang xảy ra là khi một phím được nhấn không có gì xảy ra những gì nên xảy ra là số nguyên là lớp B nên thay đổi vì lớp E tuy nhiên nó không phải là. Khi đậu net không cho phép tôi gỡ lỗi hai luồng cùng một lúc, nó làm cho nó hơi lúng túng, khi tôi đặt các điểm ngắt trong mã bên ngoài của chuỗi trong lớp E, nó không hoạt động, như thể luồng không chạy hoặc nếu nó không nhận được keyevent, nếu tôi đặt breakpoint trong thread và không phải bên ngoài nó hoạt động, giá trị của tôi trong lớp B được thay đổi. Nếu nó chạy bên ngoài gỡ lỗi nó liều không hoạt động:/

+0

Hiện nguồn. Làm thế nào là trường hợp của lớp E nhận được một tham chiếu đến lớp B? – digitaljoel

+0

Bạn nói rằng "trong khi gỡ lỗi biến không thay đổi". Bạn có thể đăng các mã nơi gỡ lỗi được in và mã (trong lớp khác) mà sửa đổi biến? – KyleM

+0

Gửi đối tượng của 'ClassB' như một tham số, cho đến khi nó đạt đến' ClassE', có lẽ? – Goodwine

Trả lời

3

Lớp E không được trực tiếp thao tác các thành viên dữ liệu trong lớp B. Đó là tất cả các loại xấu. Nhưng đó không thực sự là vấn đề của bạn.

Để chuỗi GUI trong B xem các thay đổi được thực hiện bởi chuỗi trong E, bạn cần sử dụng một số loại điều khiển đồng bộ hóa. Thông thường tôi sẽ đề nghị sử dụng một AtomicInteger, tuy nhiên bạn đã đề cập một số công cụ swing, vì vậy tôi giả sử lớp B thực sự là một thành phần Swing. Trong trường hợp đó, tôi tìm thấy nó sạch hơn để giữ cho các công cụ swing trên EDT và làm cho nó E trách nhiệm gọi B trên EDT.

Đây là ý của tôi. Tôi đã loại bỏ lớp C và D vì họ chỉ là thông qua. Tôi cũng bỏ qua việc xây dựng/thiết lập và bắt đầu chuỗi. Tôi đã xóa vòng lặp bận của bạn trong E và thay thế bằng một số CountDownLatch.

/** 
* Some GUI class, should only be accessed from the EDT 
*/ 
public class B extends JPanel { 

    private int value = 0; 

    private E thatThreadObject; 

    public void setE(E e) { 
     thatThreadObject = e; 
    }  
    public void setValue(int newValue) { 
     value = newValue; 
     System.out.println("Got a new int value: " + value); 
    } 

    public void triggerKeyEvent() { 
     thatThreadObject.keyEvent(); 
    } 
} 

/** 
* Must be thread-safe, as accessed from multiple threads 
*/ 
public class E implements Runnable{ 
    private B thatGuiObject; 
    // Note, latch is only good for one-time use. 
    private final CountDownLatch latch = new CountDownLatch(1); 

    public void setB(B b) { 
     thatGuiObject = b; 
    } 

    public void keyEvent() { 
     // Wake up the waiting thread 
     latch.countDown();    
    } 

    @Override 
    public void run() { 
     try { 
      // Wait for key event forever, better than busy looping 
      latch.await(); 
      // Update B, but it's a Swing component so use EDT 
      EventQueue.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        thatGuiObject.setValue(4); 
       } 
      }); 
     } 
     catch (InterruptedException e) { 
      e.printStackTrace(); 
     }    
    } 
} 

Có một cái nhìn tại Java Concurrency Tutorial

+0

Cảm ơn sự giúp đỡ. Tôi hoàn toàn nhận thức được rằng loại cấu trúc này vi phạm gần như mọi định luật đối tượng định hướng mô hình, tuy nhiên nhiều như nó đau tôi để làm điều này nó phải được thực hiện như khách hàng đã yêu cầu nó được theo cách này :(. – Samishalt

+0

Tôi đã thêm số nguyên nguyên tử vào hệ thống, vẫn chưa hoạt động đúng khi chạy Nếu tôi đặt điểm ngắt trong Thread trong lớp E và chạy debug thì mọi thứ đều hoạt động. Không chắc tôi có thể làm gì khác không quá quen thuộc với đồng thời trong Java:/ – Samishalt

+0

Bạn có thể thêm một số mã khác vào câu hỏi của bạn không? Cụ thể là mã trong B đang được gọi từ E và mã trong E nơi sự kiện quan trọng được chuyển vào, cũng như mã mà sau đó gọi B Bạn cũng có thể làm rõ những gì không hoạt động? Mã trong E không bao giờ nhận được sự kiện quan trọng, là B không bao giờ được gọi, là B được gọi là nhưng giá trị không thay đổi? – wolfcastle