दिलचस्प पोस्ट
जीसीसी को एक अप्रयुक्त स्थैतिक पुस्तकालय लिंक करने के लिए कैसे लागू करें सूची दृश्य आइटम नहीं काम करें "क्लोनिंग" पंक्ति या स्तंभ वैक्टर आर में कुशलता से कार्यान्वयन कैसे करें -XX: MaxPermSize के बिना या बिना-XX: PermSize जावा में गणित अभिव्यक्ति के मूल्यांकन के लिए विधि मैं स्ट्रिंग ऑब्जेक्ट को हैश ऑब्जेक्ट में कैसे रूपांतरित कर सकता हूं? JQuery के साथ div तत्वों का अनुक्रम रैंडम करना डॉक्टर और डॉकेक्स से पाठ निकालें डेटाबेस में आप प्रभावशाली मॉडल कैसे प्राप्त कर सकते हैं? संग्रह में गुणों के मानचित्रण के लिए मानचित्र / कम का उपयोग करना क्या अधिक कुशल है: शब्दकोश TryGetValue या ContainsKey + Item? जहां फ़ाइलों को संग्रहीत किया जाता है – उबंटू लिनक्स, जीसीसी x86 / x64 सीपीयू सी # में एंड्रॉइड – ऑनक्लिक पर ऐप थीम बदलें

घड़ी सेवा और स्विंगवार्कर: यह कैसे सही ढंग से करना है?

WatchService एक रोमांचक विचार की तरह लग रहा था … दुर्भाग्य से यह कम स्तर के रूप में ट्यूटोरियल / एपीआई में चेतावनी दी वास्तव में स्विंग घटना मॉडल में फिट नहीं है (या मुझे कुछ स्पष्ट, एक शून्य शून्य संभावना

ट्यूटोरियल में वॉचडायर उदाहरण से कोड लेना (केवल एक ही निर्देशिका को संभाल करने के लिए बस), मैं मूलतः समाप्त हुआ

  • स्विंगवर्कर का विस्तार करें
  • कन्स्ट्रक्टर में पंजीकरण सामग्री करते हैं
  • doInBackground में एक कुंजी के लिए इंतजार कर रहे अंतहीन लूप डाल दिया
  • प्रत्येक WatchEvent प्रकाशित करें जब key.pollEvents () के द्वारा प्राप्त किया गया
  • संपत्ति को फायरिंग द्वारा विखंडू को संसाधित करेंगूगल के रूप में हटाए गए / बनाई गई फ़ाइलों के साथ चेंजइवेंट्स

    @SuppressWarnings("unchecked") public class FileWorker extends SwingWorker<Void, WatchEvent<Path>> { public static final String DELETED = "deletedFile"; public static final String CREATED = "createdFile"; private Path directory; private WatchService watcher; public FileWorker(File file) throws IOException { directory = file.toPath(); watcher = FileSystems.getDefault().newWatchService(); directory.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); } @Override protected Void doInBackground() throws Exception { for (;;) { // wait for key to be signalled WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return null; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); // TBD - provide example of how OVERFLOW event is handled if (kind == OVERFLOW) { continue; } publish((WatchEvent<Path>) event); } // reset key return if directory no longer accessible boolean valid = key.reset(); if (!valid) { break; } } return null; } @Override protected void process(List<WatchEvent<Path>> chunks) { super.process(chunks); for (WatchEvent<Path> event : chunks) { WatchEvent.Kind<?> kind = event.kind(); Path name = event.context(); Path child = directory.resolve(name); File file = child.toFile(); if (StandardWatchEventKinds.ENTRY_DELETE == kind) { firePropertyChange(DELETED, null, file); } else if (StandardWatchEventKinds.ENTRY_CREATE == kind) { firePropertyChange(CREATED, null, file); } } } } 

बुनियादी विचार कोड को चंचल विवरणों से भली भांति अनजान बनाकर उपयोग करना है: यह संपत्ति के परिवर्तनों को सुनता है और यथासंभव उचित मानदंडों को अपडेट करता है:

  String testDir = "D:\\scans\\library"; File directory = new File(testDir); final DefaultListModel<File> model = new DefaultListModel<File>(); for (File file : directory.listFiles()) { model.addElement(file); } final FileWorker worker = new FileWorker(directory); PropertyChangeListener l = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (FileWorker.DELETED == evt.getPropertyName()) { model.removeElement(evt.getNewValue()); } else if (FileWorker.CREATED == evt.getPropertyName()) { model.addElement((File) evt.getNewValue()); } } }; worker.addPropertyChangeListener(l); JXList list = new JXList(model); 

काम करने लगता है, लेकिन मुझे असहज महसूस होता है

  • अपने आप को धागा अज्ञेयवादी के रूप में बाहर कर रहा हूं: सभी उदाहरण स्निपेट जो मैंने अभी तक देखा है watcher.take () का उपयोग करके प्रतीक्षा धागा को रोकें। वे ऐसा क्यों करते हैं? कम से कम कुछ प्रयोग watcher.poll () की अपेक्षा करें और थोड़ा सो जाओ
  • स्विंगवॉर्कर प्रकाशित पद्धति काफी फिट नहीं लगती है: क्योंकि अब यह ठीक है, क्योंकि मैं केवल एक निर्देशिका देख रहा हूं (गलत दिशा में बहुत दूर गैलोप करना नहीं चाहता था 🙂 कई निर्देशिका देखने की कोशिश करते समय (जैसा कि मूल वॉचडायर उदाहरण) उनमें से एक के सापेक्ष कई चाबियाँ और वॉचएवेंट हैं पथ को हल करने के लिए, मुझे घटना और निर्देशिका [ए] की दोनों की आवश्यकता होगी – कुंजी देख रही है – लेकिन केवल एक ही पर पारित कर सकते हैं सबसे शायद तर्क गलत वितरण का मिला, यद्यपि

[ए] संपादित (ट्रिशगोल्ड की टिप्पणी द्वारा ट्रिगर किया गया) – यह वास्तव में घटना के साथ-साथ मेरे लिए पास की कुंजी नहीं है, यह वह निर्देशिका है जिस पर परिवर्तन की रिपोर्टिंग हो रही है। तदनुसार सवाल बदल दिया

एफवाईआई, यह प्रश्न ओटीएन स्विंग फोरम पर क्रॉस-पोस्ट किया गया है

परिशिष्ट

वॉचकी के एपीआई डॉक्टर को पढ़ना:

जहां वॉच सेवा से सिग्नल कुंजियों को पुनः प्राप्त करने वाले कई धागे हैं, यह सुनिश्चित करने के लिए ध्यान रखना चाहिए कि रीसेट विधि केवल ऑब्जेक्ट की घटनाओं के बाद ही संसाधित की गई है।

लगता है कि घटनाओं को चाहिए

  1. एक ही धागे पर संसाधित किया जाना चाहिए जो वॉचकी को पुनर्प्राप्त करता है
  2. की रीसेट के बाद छुआ नहीं जाना चाहिए

पूरी तरह से निश्चित नहीं है, लेकिन (भविष्य की) आवश्यकता के साथ मिलकर निर्देशिकाओं को देखने के लिए (एक से अधिक) ईएलएस सलाह का पालन करने का निर्णय लिया है – जैसे –

संपादित करें ने अपना अपना जवाब स्वीकार कर लिया – नम्रता से वापस लौट जाएगा कि अगर कोई उचित आपत्ति है

Solutions Collecting From Web of "घड़ी सेवा और स्विंगवार्कर: यह कैसे सही ढंग से करना है?"

दरअसल, @ एल्स की टिप्पणी ने मेरे सिर के पीछे दस्तक नहीं रोक दिया – और अंत में पंजीकृत किया: यह जाने का तरीका है, लेकिन किसी भी "कृत्रिम" संरचना की कोई आवश्यकता नहीं है, क्योंकि हमारे पास पहले से ही सही उम्मीदवार हैं – यह PropertyChangeEvent है अपने आप 🙂

मेरे प्रश्न से समग्र प्रक्रिया विवरण लेते हुए, पहले तीन गोलियां एक समान रहती हैं I

  • वही: स्विंग वर्कर का विस्तार करें
  • वही: कन्स्ट्रक्टर में पंजीकरण सामग्री करते हैं
  • वही: doInBackground में एक कुंजी के लिए अंतहीन लूप इंतजार करना
  • बदल दिया: प्रत्येक WatchEvent से उचित PropertyChangeEvent बनाएँ, जब key.pollEvents के माध्यम से प्राप्त किया गया और PropertyChangeEvent प्रकाशित करें
  • परिवर्तित: प्रक्रिया में पहले से बनाए गए ईवेंट को आग लगाओ (विखंडू)

संशोधित FileWorker :

 @SuppressWarnings("unchecked") public class FileWorker extends SwingWorker<Void, PropertyChangeEvent> { public static final String FILE_DELETED = StandardWatchEventKinds.ENTRY_DELETE.name(); public static final String FILE_CREATED = StandardWatchEventKinds.ENTRY_CREATE.name(); public static final String FILE_MODIFIED = StandardWatchEventKinds.ENTRY_MODIFY.name(); // final version will keep a map of keys/directories (just as in the tutorial example) private Path directory; private WatchService watcher; public FileWorker(File file) throws IOException { directory = file.toPath(); watcher = FileSystems.getDefault().newWatchService(); directory.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); } @Override protected Void doInBackground() throws Exception { for (;;) { // wait for key to be signalled WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return null; } for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind<?> kind = event.kind(); // TBD - provide example of how OVERFLOW event is handled if (kind == OVERFLOW) { continue; } publish(createChangeEvent((WatchEvent<Path>) event, key)); } // reset key return if directory no longer accessible boolean valid = key.reset(); if (!valid) { break; } } return null; } /** * Creates and returns the change notification. This method is called from the * worker thread while looping through the events as received from the Watchkey. * * @param event * @param key */ protected PropertyChangeEvent createChangeEvent(WatchEvent<Path> event, WatchKey key) { Path name = event.context(); // real world will lookup the directory from the key/directory map Path child = directory.resolve(name); PropertyChangeEvent e = new PropertyChangeEvent(this, event.kind().name(), null, child.toFile()); return e; } @Override protected void process(List<PropertyChangeEvent> chunks) { super.process(chunks); for (PropertyChangeEvent event : chunks) { getPropertyChangeSupport().firePropertyChange(event); } } } 

क्योंकि आपकी पृष्ठभूमि थ्रेड पूरी तरह से देखने के लिए समर्पित है, take() सही विकल्प है यह प्लेटफॉर्म पर निर्भर कार्यान्वयन को छिपाता है, जो या तो आगे या पोल कर सकता है। poll() तरीकों में से एक उचित होगा, उदाहरण के लिए, WatchService साथ श्रृंखला में अन्य कतारों की जांच करने के लिए आपके पृष्ठभूमि थ्रेड को भी आवश्यक है

परिशिष्ट: क्योंकि WatchKey पास राज्य है, इसलिए इसे process() करने के लिए अग्रेषित नहीं होना चाहिए process()WatchEvent का context() "घड़ी सेवा के साथ पंजीकृत निर्देशिका और प्रविष्टि, हटाए गए या संशोधित किए गए प्रविष्टि के बीच एक सापेक्ष पथ है।" एक resolve() तरीकों को काम करना चाहिए यदि निर्देशिका एक समान रूट साझा करते हैं

अपने दूसरे बिंदु के संबंध में, क्या आप एक ऐसा वर्ग नहीं बना सकते हैं, जो वॉचआइवेंट और चाबी दोनों रखता है और स्विंगवॉर्कर के दूसरे जेनेरिक पैरामीटर इस प्रकार हो? क्षमा करें, मुझे पता है कि आपने पहले से ही इसके बारे में सोचा है, इसलिए मुझे लगता है मेरा प्रश्न यह है: ऐसा करने के लिए कोई नीचे की ओर?