2009-09-10 5 views
5

के लिए धागे में सिंक्रनाइज़ेशन मेरे पास मेरे ऐप में एक घर उगाया गया वेब सर्वर है। यह वेब सर्वर स्वीकार्य होने के लिए सॉकेट में आने वाले प्रत्येक अनुरोध के लिए एक नया धागा बनाता है। मैं चाहता हूं कि वेब सर्वर तब तक इंतजार करे जब तक कि उस थ्रेड में एक विशिष्ट बिंदु हिट न हो जाए।जावा

मैं इस साइट पर कई पोस्ट और वेब पर उदाहरणों के माध्यम से रहा हूं, लेकिन थ्रेड को प्रतीक्षा करने के बाद वेब सर्वर आगे बढ़ने के लिए नहीं मिल सकता। एक बुनियादी कोड उदाहरण बहुत अच्छा होगा।

क्या सिंक्रनाइज़ किए गए कीवर्ड को इसके बारे में जाने का सही तरीका है? यदि हां, तो यह कैसे प्राप्त किया जा सकता है? कोड उदाहरण मेरे ऐप्लिकेशन के नीचे हैं:

वेब सर्वर

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

थ्रेड कोड

public void run() { 
    //code here 

    //notify web server to continue here 
} 

अद्यतन - अंतिम कोड के रूप में नीचे है। HttpRequest सिर्फ resumeListener.resume() फोन करता है जब भी मैं एक प्रतिक्रिया हेडर भेज (बेशक एक अलग वर्ग के रूप में इंटरफेस और HttpRequest में addResumeListener(ResumeListener r1) विधि जोड़ने):

वेब सर्वर भाग

// 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

बस एक अकादमिक प्रश्न के रूप में, तुम क्यों अपने वेब सर्वर कोड लिखा? – MattC

+0

ऐप एन्क्रिप्टेड सामग्री प्रदर्शित करता है, इसलिए मूल रूप से अपना स्वयं का आंतरिक वेब सर्वर बनाकर, मैं प्रमाणीकरण कर सकता हूं। यदि कोई बाहरी ब्राउज़र उसी सॉकेट का उपयोग करने का प्रयास करता है, तो मैं डेटा पास कर रहा हूं, तो मेरे पास ऐप से अनुरोध होने पर आंतरिक रूप से आपूर्ति करने वाले उचित प्रमाण-पत्र नहीं होंगे। – Ken

+0

मुझे नहीं लगता कि यह एक अलग वेबसर्वर का उपयोग करने से कैसे रोकता है - लगभग हर वेब सर्वर अन्य तंत्रों के बीच आईपी-आधारित प्रमाणीकरण का समर्थन करता है। – bdonlan

उत्तर

1

सबसे पहले, मैं दूसरों की भावना को प्रतिबिंबित करता हूं कि यहां पहिया का पुन: आविष्कार करने से आपके लिए कई प्रकार के मुद्दों का कारण बन जाएगा। हालांकि, अगर आप इस सड़क पर जाना चाहते हैं वैसे भी जो आप करने की कोशिश कर रहे हैं वह मुश्किल नहीं है। क्या आपने जेटी के साथ प्रयोग किया है?

हो सकता है कि कुछ इस तरह:

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

उदाहरण के लिए धन्यवाद। यह बहुत सीधे आगे लगता है और मैं इसे भी एक कोशिश दूंगा। मैं अपने स्वयं के वेब सर्वर को लागू करने की चिंताओं को समझता हूं मैंने जेटी में पहले ही संक्षेप में देखा है, लेकिन इसके साथ आगे नहीं बढ़ पाया। जेटी अभी भी भविष्य के लिए एक संभावना है, लेकिन अभी घर उगाया जा रहा है अच्छी तरह से प्रदर्शन कर रहा है। – Ken

7

आप उपयोग कर सकते हैं java.util.concurrent.CountDownLatch इसके लिए 1 की गिनती के साथ। माता-पिता और बच्चे धागे द्वारा बनाए और साझा किए जाने के उदाहरण के लिए व्यवस्थित करें (उदाहरण के लिए, इसे HttpRequest के निर्माता में बनाएं, और इसे किसी सदस्य फ़ंक्शन द्वारा पुनः प्राप्त करने योग्य बनाएं)। सर्वर तब await() पर कॉल करता है, और थ्रेड countDown() हिट करता है जब यह अपने माता-पिता को रिलीज़ करने के लिए तैयार होता है।

+0

सुझाव के लिए धन्यवाद, मैं इस तरह से लागू करने की कोशिश करूंगा। काफी सरल लगता है। – Ken

3

आपको शायद जावा Condition का उपयोग करने की आवश्यकता है। डॉक्स से:

शर्तें (भी हालत के रूप में जाना कतारों या हालत चर) एक साधन प्रदान एक थ्रेड के लिए एक और धागा द्वारा ("प्रतीक्षा" के लिए) निष्पादन अधिसूचित जब तक निलंबित करने के लिए है कि कुछ राज्य हालत अब सच हो सकता है।

+1

अकेले हालत चर कोड खोलने के लिए थोड़ा मुश्किल हैं; आपको लूपिंग को रोकने और अवरुद्ध करने के बारे में जानने के लिए एक संबंधित लॉक और ध्वज की भी आवश्यकता है। इसके अलावा सीधे कंडीशन क्लास का उपयोग करने की आवश्यकता नहीं है; बस प्रत्येक ऑब्जेक्ट में मॉनिटर निहित का उपयोग करें ... – bdonlan

+0

इसके अलावा, थोड़ा स्पष्ट करने के लिए - हालत/लॉक एक और स्पष्ट प्रणाली के लिए बनाते हैं, लेकिन एक जो सिंक्रनाइज़ किए गए मॉनीटर से स्वतंत्र है और 'ऑब्जेक्ट.वेट'() '। यदि आप एक लॉक से जुड़े एकाधिक हालत चर की आवश्यकता होती है, तो वे उपयोगी होंगे, लेकिन इस मामले में यह अधिक मात्रा में है। – bdonlan

+0

असल में 'कंडीशन' एक इंटरफेस है, मैं इसे केवल एक कार्यान्वयन वर्ग का उपयोग करने के रूप में इंगित कर रहा था अभ्यास में आवश्यक होगा। जिस पृष्ठ से मैंने लिंक किया है उसका एक उदाहरण 'ReentrantLock' है। –

-3

डीबगर के तहत भागो और ब्रेकपॉइंट सेट करें?

यदि असुरक्षित है, तो System.in से एक लाइन पढ़ें?

+0

कोई विचार नहीं कि यह प्रश्न से कैसे संबंधित है .... –