2009-09-10 64 views
5

Tôi có một máy chủ web được phát triển trong ứng dụng của mình. Máy chủ web này sinh ra một chuỗi mới cho mọi yêu cầu đi vào ổ cắm để được chấp nhận. Tôi muốn máy chủ web đợi cho đến khi một điểm cụ thể được nhấn vào chuỗi mà nó vừa tạo.Đồng bộ hóa trong chủ đề cho Java

Tôi đã trải qua nhiều bài đăng trên trang web này và các ví dụ trên web, nhưng không thể yêu cầu máy chủ web tiếp tục sau khi tôi yêu cầu chuỗi chờ. Một ví dụ mã cơ bản sẽ là tuyệt vời.

Từ khóa được đồng bộ hóa có đúng cách để thực hiện việc này không? Nếu vậy, làm thế nào điều này có thể đạt được? Mã số ví dụ dưới của ứng dụng của tôi:

Web Server

while (true) { 
    //block here until a connection request is made 
    socket = server_socket.accept(); 

    try { 
    //create a new HTTPRequest object for every file request 
    HttpRequest request = new HttpRequest(socket, this); 

    //create a new thread for each request 
    Thread thread = new Thread(request); 

    //run the thread and have it return after complete 
    thread.run(); 

    /////////////////////////////// 
    wait here until notifed to proceed 
    /////////////////////////////// 
    } catch (Exception e) { 
    e.printStackTrace(logFile); 
    } 
} 

Chủ đề đang

public void run() { 
    //code here 

    //notify web server to continue here 
} 

Update - Mã cuối cùng là như dưới đây. Các HttpRequest không chỉ cần gọi resumeListener.resume() bất cứ khi nào tôi gửi một đáp ứng tiêu đề (tất nhiên cũng có thêm giao diện như là một lớp riêng biệt và addResumeListener(ResumeListener r1) phương pháp trong HttpRequest):

phần Web Server

// server infinite loop 
while (true) { 

    //block here until a connection request is made 
    socket = server_socket.accept(); 

    try { 
    final Object locker = new Object(); 

    //create a new HTTPRequest object for every file request 
    HttpRequest request = new HttpRequest(socket, this); 

    request.addResumeListener(new ResumeListener() { 
     public void resume() { 
     //get control of the lock and release the server 
     synchronized(locker) { 
      locker.notify(); 
     } 
     } 
    }); 

    synchronized(locker) { 
     //create a new thread for each request 
     Thread thread = new Thread(request); 

     //run the thread and have it return after complete 
     thread.start(); 

     //tell this thread to wait until HttpRequest releases 
     //the server 
     locker.wait(); 
    } 
    } catch (Exception e) { 
    e.printStackTrace(Session.logFile); 
    } 
} 
+0

Cũng giống như một câu hỏi học tập, tại sao bạn viết mã máy chủ web của riêng bạn? – MattC

+0

Ứng dụng hiển thị nội dung được mã hóa, vì vậy về cơ bản bằng cách tạo máy chủ web nội bộ của riêng tôi, tôi có thể thực hiện xác thực. Nếu một trình duyệt bên ngoài cố gắng sử dụng cùng một socket tôi đang truyền dữ liệu qua, nó sẽ không có thông tin đăng nhập phù hợp mà tôi cung cấp nội bộ nếu yêu cầu đến từ ứng dụng của tôi. – Ken

+0

Tôi không thấy cách ngăn cản việc sử dụng máy chủ web khác - hầu như mọi máy chủ web đều hỗ trợ xác thực dựa trên IP, trong số các cơ chế khác. – bdonlan

Trả lời

1

Trước hết, tôi lặp lại cảm xúc của người khác rằng việc phát minh lại bánh xe ở đây rất có thể sẽ dẫn đến nhiều vấn đề khác nhau cho bạn. Tuy nhiên, nếu bạn muốn đi xuống con đường này thì những gì bạn đang cố gắng làm là không khó. Bạn đã thử nghiệm với Jetty chưa?

Có lẽ một cái gì đó như thế này:

public class MyWebServer { 

    public void foo() throws IOException { 
    while (true) { 
     //block here until a connection request is made 
     ServerSocket socket = new ServerSocket(); 

     try { 
     final Object locker = new Object(); 
     //create a new HTTPRequest object for every file request 
     MyRequest request = new MyRequest(socket); 
     request.addResumeListener(new ResumeListener() { 
      public void resume() { 
      locker.notify(); 
      } 
     }); 
     synchronized(locker){ 

      //create a new thread for each request 
      Thread thread = new Thread(request); 

      //start() the thread - not run() 
      thread.start(); 

      //this thread will block until the MyRequest run method calls resume 
      locker.wait(); 
     } 
     } catch (Exception e) { 
     } 

    } 
    } 
} 

public interface ResumeListener { 
    public void resume(); 
} 

public class MyRequest implements Runnable{ 
    private ResumeListener resumeListener; 

    public MyRequest(ServerSocket socket) { 
    } 

    public void run() { 
    // do something 
    resumeListener.resume(); //notify server to continue accepting next request 
    } 

    public void addResumeListener(ResumeListener rl) { 
    this.resumeListener = rl; 
    } 
} 
+0

Cảm ơn ví dụ. Nó có vẻ khá thẳng về phía trước và tôi cũng sẽ thử nó. Tôi hiểu những lo ngại về việc triển khai máy chủ web của riêng tôi, tôi đã xem xét Jetty một thời gian ngắn, nhưng không đi tiếp với nó. Cầu tàu vẫn là một khả năng cho tương lai, nhưng ngay bây giờ ngôi nhà trưởng thành đang hoạt động tốt. – Ken

7

Bạn có thể sử dụng java.util.concurrent.CountDownLatch với tổng số là 1 cho điều này. Sắp xếp cho một ví dụ của nó được tạo ra và được chia sẻ bởi các chủ đề cha và con (ví dụ, tạo nó trong constructor HttpRequest ', và có nó có thể truy xuất bởi một hàm thành viên). Máy chủ sau đó gọi số await() trên đó và chuỗi truy cập countDown() khi nó sẵn sàng phát hành phụ huynh của nó.

+0

Cảm ơn bạn đã gợi ý, tôi sẽ thử thực hiện theo cách này. Có vẻ đơn giản là đủ. – Ken

3

Có thể bạn cần sử dụng Java Condition. Từ các tài liệu:

Điều kiện (còn gọi là tình trạng hàng đợi hoặc các biến điều kiện) cung cấp một phương tiện cho một thread để đình chỉ thực hiện (để "chờ") cho đến khi thông báo bởi thread khác mà một số nhà nước tình trạng bây giờ có thể đúng.

+1

Biến điều kiện là một chút khó khăn để mở mã; bạn cũng cần một Khóa liên quan và một lá cờ để biết khi nào nên dừng vòng quanh và chặn. Ngoài ra, không cần sử dụng trực tiếp lớp Điều kiện; chỉ cần sử dụng màn hình ngầm trong mọi đối tượng ... – bdonlan

+0

Ngoài ra, để làm rõ một chút - Điều kiện/Khóa làm cho một hệ thống rõ ràng hơn, nhưng nó độc lập với các màn hình tích hợp được sử dụng bởi 'sync' và' Object.wait() '. Chúng sẽ hữu ích nếu bạn cần nhiều biến điều kiện gắn liền với một khóa duy nhất, nhưng trong trường hợp này nó là quá mức cần thiết. – bdonlan

+0

Thực ra 'Điều kiện 'là một giao diện, tôi chỉ chỉ ra nó khi sử dụng một lớp thực hiện sẽ cần thiết trong thực tế. Trang tôi liên kết có một ví dụ với 'ReentrantLock's. –

-3

Chạy dưới trình gỡ rối và đặt điểm ngắt?

Nếu không đọc được, hãy đọc một dòng từ System.in?

+0

Không biết làm thế nào điều này liên quan đến câu hỏi .... –

Các vấn đề liên quan