2010-08-21 17 views
42

नेटबीन में, एक नया संकेत है जो कहता है: थ्रेड स्लीप लूप में बुलाया जाता है।नेटबीन/जावा/नया संकेत: थ्रेड स्लीप लूप

प्रश्न 1: कैसे/जब यह एक पाश में सोने के लिए एक समस्या हो सकता है?

प्रश्न 2: यदि यह कोई समस्या है, तो मुझे इसके बजाय क्या करना चाहिए?

अद्यतन: प्रश्न 3: यहां कुछ कोड है। मुझे इस मामले में बताओ अगर मुझे थ्रेड के बजाए कुछ और इस्तेमाल करना चाहिए। लूप में सो जाओ। संक्षेप में, यह एक सर्वर द्वारा उपयोग किया जाता है जो क्लाइंट टीसीपी कनेक्शन के लिए सुनता है। ग्राहकों के साथ सत्रों की अधिकतम संख्या तक पहुंचने पर नींद का उपयोग यहां किया जाता है। इस स्थिति में, मैं चाहता हूं कि एक निःशुल्क सत्र उपलब्ध होने तक एप्लिकेशन प्रतीक्षा करें।

public class SessionManager { 
    private static final int DEFAULT_PORT = 7500; 
    private static final int SLEEP_TIME = 200; 
    private final DatabaseManager database = new DatabaseManager(); 
    private final ServerSocket serverSocket = new ServerSocket(DEFAULT_PORT); 

public SessionManager() throws IOException, SQLException 
{ 
} 

public void listen() 
{ 
while (true) 
    if (Session.getSessionCount() < Session.getMaxSessionCount()) 
     try 
     { 
      new Thread(new Session(database, serverSocket.accept())).start(); 
     } 
     catch (IOException ex) { ex.printStackTrace(); } 
    else 
     try 
     { 
      Thread.sleep(SLEEP_TIME); 
     } 
     catch (InterruptedException ex) { ex.printStackTrace(); } 
} 

public static void main(String[] args) throws IOException, SQLException 
{ 
new SessionManager().listen(); 
} 
} 

उत्तर

19

लूप में नींद को बुलाकर आम तौर पर खराब प्रदर्शन होता है। उदाहरण के लिए:

while (true) { 
    if (stream.available() > 0) { 
     // read input 
    } 
    sleep(MILLISECONDS); 
} 

यदि मिलीलीकोन्ड्स बहुत बड़ा है, तो इस कोड को यह समझने में काफी समय लगेगा कि इनपुट उपलब्ध है।

यदि मिलिसेकोन्ड्स बहुत छोटा है, तो यह कोड इनपुट सिस्टम के लिए बहुत सारे सिस्टम संसाधनों को जांच देगा जो अभी तक नहीं पहुंचे हैं।

लूप में sleep के अन्य उपयोग आमतौर पर भी संदिग्ध होते हैं। आमतौर पर एक बेहतर तरीका है।

यदि यह कोई समस्या है, तो मुझे इसके बजाय क्या करना चाहिए?

कोड पोस्ट करें और शायद हम आपको एक समझदार उत्तर दे सकते हैं।

संपादित

IMO, समस्या को हल करने के लिए एक बेहतर तरीका है एक ThreadPoolExecutor उपयोग करने के लिए है।

कुछ इस तरह:

public void listen() { 
    BlockingQueue queue = new SynchronousQueue(); 
    ThreadPoolExecutor executor = new ThreadPoolExecutor(
      1, Session.getMaxSessionCount(), 100, TimeUnit.SECONDS, queue); 
    while (true) { 
     try { 
      queue.submit(new Session(database, serverSocket.accept())); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 
} 

इस निष्पादक तरीका है अपने कोड वर्तमान में काम करता है मिलान करने के लिए कॉन्फ़िगर करता है। आप इसे करने के कई अन्य तरीके भी कर सकते हैं; ऊपर जावाडोक लिंक देखें।

+0

एक java.util.Timer और आवधिक टाइमरटास्क के बारे में कैसे? – Core

+0

@ कोर - यह इस बात पर निर्भर करता है कि आप इसका उपयोग कैसे करते हैं। यदि आप इसे 'नींद()' के बराबर लागू करने के लिए उपयोग करते हैं, तो आपको 'नींद() 'का उपयोग करने जैसी ही समस्याएं हैं। –

+0

क्या होगा यदि हम प्रबंधितexecutorservice का उपयोग कर रहे हैं? – wib

2

कैसे/जब यह एक पाश में सोने के लिए एक समस्या हो सकता है?
लोग कभी-कभी उचित सिंक्रनाइज़ेशन विधियों (जैसे प्रतीक्षा/सूचित) के स्थान पर इसे नियोजित करते हैं।

यदि यह कोई समस्या है, तो मुझे इसके बजाय क्या करना चाहिए?
आप जो कर रहे हैं उस पर निर्भर करता है। यद्यपि यह मेरे लिए परिस्थिति की कल्पना करने के लिए भिन्न है, जहां यह करना सबसे अच्छा तरीका है, मुझे लगता है कि यह भी संभव है।

आप इस विषय पर देख सकते हैं।

+0

लोगों को भी कभी कभी यह पढ़ने छोरों में उपलब्ध परीक्षण(), के साथ संयोजन के रूप में उपयोग करते हैं, जब वे बस के बजाय समय और स्थान बर्बाद कर के पढ़ में अवरुद्ध किया जाना चाहिए। – EJP

+0

एक उपयोग एक निर्देशिका क्लीनर है, जो एक निश्चित अवधि से पुरानी फ़ाइलों को हटा देता है। पहले भाग के बाद, हम जानते हैं कि सबसे पुरानी फ़ाइल कौन सा है, और यह कितनी देर तक "बहुत पुरानी" बन जाती है, इसलिए हम उस अवधि के लिए सो सकते हैं। – Jesse

+0

@ जेसे - एक निर्धारित थ्रेड पूल निष्पादक शायद इसके लिए बेहतर होगा। –

3

जैसा कि अन्य ने कहा है कि यह उपयोग पर निर्भर करता है।एक वैध उपयोग एक ऐसा प्रोग्राम होगा जो हर 10 सेकंड में कुछ करने के लिए डिज़ाइन किया गया है (लेकिन इतना महत्वपूर्ण नहीं है कि सटीक समय की आवश्यकता हो)। हमारे पास इनमें से बहुत से "उपयोगिता ऐप्स" हैं जो हर कुछ मिनट में डेटा और अन्य ऐसे कार्यों को आयात करते हैं। यह इन कार्यों को करने का एक आसान तरीका है और हम आम तौर पर नींद अंतराल को बहुत कम होने के लिए सेट करेंगे और काउंटर का उपयोग करेंगे ताकि कार्यक्रम उत्तरदायी रहे और आसानी से बाहर निकल सके।

int count = 0; 
while (true) { 

    try { 
     // Wait for 1 second. 
     Thread.sleep(1000); 
    } 
    catch (InterruptedException ex) {} 

    // Check to see if the program should exit due to other conditions. 
    if (shouldExit()) 
     break; 

    // Is 10 seconds up yet? If not, just loop back around. 
    count++; 
    if (count < 10) continue; 

    // 10 seconds is up. Reset the counter and do something important. 
    count = 0; 
    this.doSomething(); 
} 
+1

इसके बजाय एक निर्धारित थ्रेड पूल निष्पादक का उपयोग करना ज्यादातर मामलों में तकनीकी रूप से बेहतर होगा, लेकिन कभी-कभी यह बहुत अधिक होता है जब आप केवल कुछ त्वरित और गंदे प्रोग्रामिंग कर रहे होते हैं। – mjaggard

+0

@mjaggard कहता है कि मेरे पास वर्तमान में नींद के साथ एक लूप के साथ एक धागा है। यह हाउसकीपिंग कार्यों को कर रहा है जैसे पुराने डेटा को शुद्ध करना जो अब प्रासंगिक नहीं है। अनुसूचित थ्रेड पूल निष्पादक का उपयोग करना, लंबे समय तक रहने वाले, अधिकतर निष्क्रिय धागे की तुलना में, कोड में अनावश्यक जटिलता जोड़ देगा। संदर्भ स्विच जुर्माना एक लंबे समय तक रहने वाले/निष्क्रिय धागे के लिए नगण्य है जो सो रहा है। अनुसूचित थ्रेड पूल वास्तव में आपको "एक अच्छा अभ्यास नहीं" चेतावनी को हटाने के अलावा, आपको क्या खरीदता है? – ruckc

+2

क्या आपने प्रत्येक के लिए कोड लिखा है? मुझे संदेह है कि अनुसूचित थ्रेड पूल निष्पादक संस्करण वास्तव में कम, पढ़ने में आसान और बहुत ही समान दक्षता हो सकता है। – mjaggard

1

मुझे लगता है कि मैं लूप में sleep() विधि का एक पूरी तरह से वैध उपयोग में आया हूं।

हमारे पास सर्वर और क्लाइंट के बीच एक तरफा कनेक्शन है। तो जब ग्राहक सर्वर के साथ एसिंक्रोनस संचार प्राप्त करना चाहता है, तो वह सर्वर से संदेश भेजता है और सर्वर से कुछ प्रतिक्रिया के लिए समय-समय पर चुनाव भेजता है। कुछ टाइमआउट अंतराल होने की जरूरत है।

Response resp = null; 
for (int i = 0; i < POLL_REPEAT && resp == null; i++) { 
    try { 
     Thread.sleep(POLL_INTERVAL); 
    } catch (InterruptedException ie) { 
    } 
    resp = server.getResponse(workflowId); 
} 

POLL_REPEAT * POLL_INTERVAL ~ TIMEOUT अंतराल

+1

आपके एपीआई के साथ यदि संभव हो तो एक बेहतर समाधान ब्लॉकिंग आईओ विधि का उपयोग करना होगा, जो उस समय तक इंतजार कर रहा है जब नया डेटा उपलब्ध हो। – Vitruvius

संबंधित मुद्दे