दिलचस्प पोस्ट
एक regexp के साथ ओवरलैपिंग मैचों को कैसे ढूंढें? इनपुट प्रकार = "फ़ाइल" पर कर्सर प्रकार बदलें जावा में JSON ऑब्जेक्ट में हैशप को कैसे परिवर्तित करें गिट Xcode परियोजनाओं के लिए फ़ाइल को अनदेखा करें ASP.NET MVC – यूआरएल से नियंत्रक नाम को हटाने दिनांक स्वरूप डीडी / एमएम / याय में परिवर्तित करें और ? सक्रिय विंडो का स्क्रीनशॉट कैप्चर करें? कॉम्बो बॉक्स चयनितआइटम बनाम बना दिया वैल्यू कैसे जाँचने के लिए कि एक स्ट्रिंग नियमित अभिव्यक्ति का उपयोग कर एक palindrome है? स्वत: वेतन वृद्धि के साथ mysql दो स्तंभ प्राथमिक कुंजी क्या कोई विशिष्ट Xcode संकलक ध्वज है जो iPad के लिए संकलन करते समय सेट हो जाता है? कंटेनर को सेवाओं के तर्क के रूप में कैसे देना है नोडजेज़ के साथ फाइल में एक स्ट्रिंग को बदलें जावास्क्रिप्ट में एक गाया हुआ HTML पेज के हिस्से को कैसे मुद्रित कर सकता हूं?

लूपर थ्रेड कैसे बनाएं, फिर उसे तत्काल संदेश भेजें?

मेरे पास एक कार्यकर्ता धागा है जो पृष्ठभूमि में बैठता है, संदेशों को प्रसंस्करण करता है कुछ इस तरह:

class Worker extends Thread { public volatile Handler handler; // actually private, of course public void run() { Looper.prepare(); mHandler = new Handler() { // the Handler hooks up to the current Thread public boolean handleMessage(Message msg) { // ... } }; Looper.loop(); } } 

मुख्य थ्रेड (UI थ्रेड से, यह महत्वपूर्ण नहीं है) मैं इस तरह कुछ करना चाहूंगा:

 Worker worker = new Worker(); worker.start(); worker.handler.sendMessage(...); 

परेशानी यह है कि यह मुझे एक सुंदर दौड़ की स्थिति के लिए सेट करती है: समय पर worker.handler पढ़ा जाता है, यह सुनिश्चित करने का कोई तरीका नहीं है कि कार्यकर्ता थ्रेड पहले से ही इस फ़ील्ड को सौंप दिया गया है!

मैं बस Worker के निर्माता से Handler नहीं बना सकता, क्योंकि कन्स्ट्रक्टर मुख्य थ्रेड पर चलता है, इसलिए Handler स्वयं को गलत धागा से जोड़ देगा।

यह शायद ही असामान्य परिदृश्य की तरह लगता है। मैं कई कामकाज के साथ आ सकता हूं, उन सभी को बदसूरत:

  1. कुछ इस तरह:

     class Worker extends Thread { public volatile Handler handler; // actually private, of course public void run() { Looper.prepare(); mHandler = new Handler() { // the Handler hooks up to the current Thread public boolean handleMessage(Message msg) { // ... } }; notifyAll(); // <- ADDED Looper.loop(); } } 

    और मुख्य धागा से:

     Worker worker = new Worker(); worker.start(); worker.wait(); // <- ADDED worker.handler.sendMessage(...); 

    लेकिन यह विश्वसनीय नहीं है: यदि notifyAll() wait() से पहले होती है, तो हम कभी भी जाग नहीं notifyAll() !

  2. Worker के निर्माता के लिए एक प्रारंभिक Message उत्तीर्ण करना, run() पद्धति को पोस्ट करने के बाद। एक तदर्थ समाधान, कई संदेशों के लिए काम नहीं करेगा, या अगर हम इसे तुरंत भेजना नहीं चाहते हैं, लेकिन जल्द ही बाद में।

  3. जब तक handler फ़ील्ड अब तक null नहीं है तब तक प्रतीक्षा-व्यस्त। हां, आखिरी उपाय …

मैं Worker धागा की ओर से एक Handler और MessageQueue बनाना चाहता हूं, लेकिन यह संभव नहीं लगता है। इस से बाहर सबसे खूबसूरत तरीका क्या है?

Solutions Collecting From Web of "लूपर थ्रेड कैसे बनाएं, फिर उसे तत्काल संदेश भेजें?"

अंततः समाधान (शून्य से त्रुटि जांच), धन्यवाद कॉमन्सवर:

 class Worker extends HandlerThread { // ... public synchronized void waitUntilReady() { d_handler = new Handler(getLooper(), d_messageHandler); } } 

और मुख्य धागा से:

 Worker worker = new Worker(); worker.start(); worker.waitUntilReady(); // <- ADDED worker.handler.sendMessage(...); 

यह HandlerThread.getLooper() के शब्दों को धन्यवाद करता है जो लूप को आरम्भ करने तक ब्लॉक करता है।


संयोग से, यह ऊपर मेरे समाधान # 1 के समान है, क्योंकि HandlerThread निम्नानुसार लगभग लागू किया गया है (ओपन सोर्स प्यार होगा):

 public void run() { Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Looper.loop(); } public Looper getLooper() { synchronized (this) { while (mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; } 

मुख्य अंतर यह है कि यह जाँच नहीं करता कि कार्यकर्ता धागा चल रहा है या नहीं, लेकिन यह वास्तव में एक लूप बनाया है; और ऐसा करने का तरीका निजी क्षेत्र में लूप को स्टोर करना है अच्छा!

HandlerThread के स्रोत कोड पर एक नज़र HandlerThread

 @Override public void run() { mTid = Process.myTid(); Looper.prepare(); synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); onLooperPrepared(); Looper.loop(); mTid = -1; } 

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

यह मेरा समाधान है: मुख्य गतिविधि:

 //Other Code mCountDownLatch = new CountDownLatch(1); mainApp = this; WorkerThread workerThread = new WorkerThread(mCountDownLatch); workerThread.start(); try { mCountDownLatch.await(); Log.i("MsgToWorkerThread", "Worker Thread is up and running. We can send message to it now..."); } catch (InterruptedException e) { e.printStackTrace(); } Toast.makeText(this, "Trial run...", Toast.LENGTH_LONG).show(); Message msg = workerThread.workerThreadHandler.obtainMessage(); workerThread.workerThreadHandler.sendMessage(msg); 

वर्कर टेफ्रेड क्लास:

 public class WorkerThread extends Thread{ public Handler workerThreadHandler; CountDownLatch mLatch; public WorkerThread(CountDownLatch latch){ mLatch = latch; } public void run() { Looper.prepare(); workerThreadHandler = new Handler() { @Override public void handleMessage(Message msg) { Log.i("MsgToWorkerThread", "Message received from UI thread..."); MainActivity.getMainApp().runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.getMainApp().getApplicationContext(), "Message received in worker thread from UI thread", Toast.LENGTH_LONG).show(); //Log.i("MsgToWorkerThread", "Message received from UI thread..."); } }); } }; Log.i("MsgToWorkerThread", "Worker thread ready..."); mLatch.countDown(); Looper.loop(); } } 
  class WorkerThread extends Thread { private Exchanger<Void> mStartExchanger = new Exchanger<Void>(); private Handler mHandler; public Handler getHandler() { return mHandler; } @Override public void run() { Looper.prepare(); mHandler = new Handler(); try { mStartExchanger.exchange(null); } catch (InterruptedException e) { e.printStackTrace(); } Looper.loop(); } @Override public synchronized void start() { super.start(); try { mStartExchanger.exchange(null); } catch (InterruptedException e) { e.printStackTrace(); } } }