2011-08-12 9 views
7

मैं इस अभ्यास का उपयोग कुछ शैक्षिक उपकरण के रूप में कर रहा हूं ताकि मुझे कुछ जावा जीयूआई प्रोग्रामिंग अवधारणाओं में जलने में मदद मिल सके। जो मैं खोज रहा हूं वह एक सामान्य समस्या है, एक विशिष्ट समस्या के विस्तृत समाधान के बजाय। मुझे उम्मीद है कि यह "सही" कोडिंग मुझे भविष्य में बहु-थ्रेडेड समस्याओं से संपर्क करने के बारे में बहुत कुछ सिखाएगा। यदि यह इस मंच के लिए बहुत सामान्य है, तो संभवतः यह प्रोग्रामर में है?मैं स्विंगवर्कर के साथ एक बफरर्ड परिधीय डिवाइस का अनुकरण कैसे करूं?

मैं एक कार्ड रीडर अनुकरण कर रहा हूं। इसमें एक जीयूआई है, जो हमें हॉपर में कार्ड लोड करने और स्टार्ट और बहुत आगे प्रेस करने की इजाजत देता है, लेकिन इसका मुख्य "क्लाइंट" सीपीयू है, जो अलग थ्रेड पर चल रहा है और कार्ड का अनुरोध करता है।

कार्ड रीडर एक एकल बफर बनाए रखता है। यदि कोई कार्ड अनुरोध आता है और बफर खाली होता है, तो कार्ड रीडर को हॉपर से कार्ड पढ़ना चाहिए (जो एक सेकंड का 1/4 लेता है, यह 1 9 62 है)। कार्ड को बफर में पढ़ने के बाद, कार्ड रीडर सीपीयू को बफर भेजता है, और अगले अनुरोध के पहले तुरंत एक और बफर लोडिंग ऑपरेशन शुरू करता है।

यदि न केवल बफर खाली है, लेकिन हॉपर में कोई कार्ड नहीं है, तो हमें तब तक इंतजार करना चाहिए जब तक ऑपरेटर ने हॉपर में एक डेक लगाया और दबाया स्टार्ट (जो हमेशा बफर-लोड ऑपरेशन शुरू करता है)।

मेरे कार्यान्वयन में, कार्ड रीडर को कार्ड रीडर को invokeLater()Runnables के रूप में ईडीटी पर कतारबद्ध किया गया है। myRunnable.run() समय पर, या तो एक बफर उपलब्ध होगा (इस मामले में हम इसे सीपीयू को भेज सकते हैं और एक और बफर-लोड ऑपरेशन बंद कर सकते हैं), या बफर खाली हो जाएगा। क्या होगा यदि यह खाली है?

दो संभावनाएं: (ए) उड़ान में पहले से ही एक बफर लोड ऑपरेशन है, या (बी) कार्ड हॉपर खाली है (या शुरू नहीं हुआ है)। किसी भी मामले में, ईडीटी प्रतीक्षा रखने के लिए स्वीकार्य नहीं है। काम (और प्रतीक्षा) पृष्ठभूमि धागे पर किया जाना चाहिए।

सादगी के लिए, मैंने बफर की स्थिति के बावजूद प्रत्येक कार्ड अनुरोध के जवाब में एक स्विंगवर्कर को घुमाने की कोशिश की। स्यूडोकोड था:

SwingWorker worker = new SwingWorker<Void, Void>() { 
    public Void doInBackground() throws Exception { 
     if (buffer.isEmpty()) { 
      /* 
      * fill() takes 1/4 second (simulated by Thread.sleep) 
      * or possibly minutes if we need to have another 
      * card deck mounted by operator. 
      */ 
      buffer.fill(); 
     } 
     Card card = buffer.get(); // empties buffer 
     /* 
     * Send card to CPU 
     */ 
     CPU.sendMessage(card); // <== (A) put card in msg queue 
     /* 
     * Possible race window here!! 
     */ 
     buffer.fill(); //   <== (B) pre-fetch next card 
     return null; 
    } 
}; 
worker.execute(); 

यह उत्पादित कुछ अजीब समय प्रभाव - कारण, मुझे लगता है, एक buffer.fill() दौड़ इस प्रकार हो सकता है कि करने के लिए: अगर, (ए) और (बी) के बीच, सीपीयू कार्ड दिखाया गया, एक और के लिए एक अनुरोध भेजा, और एक और स्विंगवर्कर धागा अपनी ओर से पैदा हुआ था, तो बफर भरने की कोशिश कर रहे दो धागे हो सकते हैं। [प्री-फ़ेच कॉल को हटाकर (बी) को हल किया गया।]

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

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


संपादित करें: मैं another thread से एक जवाब मिला है और इसे यहाँ सारांश यह होगा: एक SwingWorker धागा उपयोग करने के बजाय

, यह सिफारिश की थी मैं एक बार एक ExecutorServicenewSingleThreadExecutor() बनाते हैं, शुरुआत में, और जीयूआई है यह execute(Runnable foo) उपयोग करते हुए, इस प्रकार पर कतारबद्ध लंबा तरीकों (इस कोड EDT में चलता है):

private ExecutorService executorService; 
:: 
/* 
* In constructor: create the thread 
*/ 
executorService = Executors.newSingleThreadExecutor(); 
:: 
/* 
* When EDT receives a request for a card it calls readCard(), 
* which queues the work out to the *single* thread. 
*/ 
public void readCard() throws Exception { 
    executorService.execute(new Runnable() { 
     public void run() { 
      if (buffer.isEmpty()) { 
       /* 
       * fill() takes 1/4 second (simulated by Thread.sleep) 
       * or possibly minutes if we need to have another 
       * card deck mounted by operator. 
       */ 
       buffer.fill(); 
      } 
      Card card = buffer.get(); // empties buffer 
      /* 
      * Send card to CPU 
      */ 
      CPU.sendMessage(card); // <== (A) put card in msg queue 
      /* 
      * No race! Next request will run on same thread, after us. 
      */ 
      buffer.fill(); //   <== (B) pre-fetch next card 
      return; 
     } 
    }); 
} 

इस और SwingWorker के बीच मुख्य अंतर यह है कि सिर्फ एक कार्यकर्ता धागा है सुनिश्चित करता है कि है।

+0

पूछताछ की एक अलग लाइन से एक काम कर जवाब मिल गया है, और मेरा उत्तर संलग्न करने के लिए मूल प्रश्न संपादित:

यहाँ मेरी संशोधित समाधान है। (अगर यह एसओ-प्रोटोकॉल-सही नहीं है तो खुशी से बदल जाएगा!) – Chap

उत्तर

5

एक बात "जवाब" से लापता मैं मूल प्रश्न के साथ जोड़ दिया था हुई:

मैं एक पृष्ठभूमि धागा करने के लिए समय लेने वाली काम (शैक्षणिक उद्देश्यों के लिए एक Thread.sleep() से ज्यादा कुछ नहीं) सौंपने था , एकल थ्रेड निष्पादक के माध्यम से। हालांकि, एक समस्या उत्पन्न हुई, क्योंकि पृष्ठभूमि धागा एक स्विंग घटक के लिए डेटा मॉडल के रूप में सेवा कर रहा था, और श्रेणी अपवादों से बाहर एडब्ल्यूटी सरणी सूचकांक को बढ़ाने के लिए सूची() द्वारा "कार्ड पढ़ना" था।ईडीटी और मेरे पृष्ठभूमि धागे दोनों द्वारा सूची तक पहुंच को सिंक्रनाइज़ करने के कई व्यर्थ प्रयासों के बाद, मैंने पंसेंट किया, और कमांड को मतदान() सूची में लपेट लिया और जीयूआई को एक छोटे से चलने योग्य() में अपडेट किया, और उपयोग के लिए invokeAndWait() का उपयोग किया उन्हें ईडीटी पर चलाने के लिए जबकि मेरा पृष्ठभूमि कार्य इंतजार कर रहा था।

private ExecutorService executorService; 
: 
executorService = Executors.newSingleThreadExecutor(); 
: 
/* 
* When EDT receives a request for a card it calls readCard(), 
* which queues the work to the *single* thread. 
*/ 
public void readCard() throws Exception { 
    executorService.execute(new Runnable() { 
     public void run() { 
      if (buffer.isEmpty()) { 
       /* 
       * fill() takes 1/4 second (simulated by Thread.sleep) 
       */ 
       buffer.fill(); 
      } 
      Card card = buffer.get(); // empties buffer 
      /* 
      * Send card to CPU 
      */ 
      CPU.sendMessage(card); // <== (A) put card in msg queue 
      /* 
      * No race! Next request will run on same thread, after us. 
      */ 
      buffer.fill(); //   <== (B) pre-fetch next card 
      return; 
     } 
    }); 
} 

/* 
* IMPORTANT MODIFICATION HERE - - - 
* 
* buffer fill() method has to remove item from the list that is the 
* model behind a JList - only safe way is to do that on EDT! 
*/ 
private void fill() { 
    SwingUtilities.invokeAndWait(new Runnable() { 
     /* 
     * Running here on the EDT 
     */ 
     public void run() { 
      /* 
      * Hopper not empty, so we will be able to read a card. 
      */ 
      buffer = readHopper.pollLast(); // read next card from current deck 
      fireIntervalRemoved(this, readHopper.size(), readHopper.size()); 
      gui.viewBottomOfHopper(); // scroll read hopper view correctly 
     } 
    }); 
    // back to my worker thread, to do 1/4 sec. of heavy number crunching ;) 
    // while leaving the GUI responsive 
    Thread.sleep(250); 
    : 
    etc. 
} 
+1

'invokeAndWait()' इस संदर्भ में सहायक है; यह भी [थ्रेड] देखें (http://groups.google.com/group/comp.lang.java.gui/browse_thread/thread/b162b2e4ea3cb371)। Comp.lang.java.gui धागे के लिंक के लिए – trashgod

+1

+1। मेरे सिर पर लगभग, अर्थशास्त्र और बाधाओं से पहले होने वाले मुद्दों के साथ, लेकिन ऐसा लगता है कि invokeAndWait() मेरे साधारण मामले में यहां काम करेगा। – Chap

5

यह जानने में मदद कर सकता है कि SwingWorker आंतरिक रूप से ExecutorService का उपयोग करता है; यह सुविधा के लिए अंतरिम ईडीटी प्रसंस्करण तंत्र जोड़ता है। जब तक आप ईडीटी पर अपना जीयूआई अपडेट करते हैं और किसी भी साझा डेटा तक पहुंच को सिंक्रनाइज़ करते हैं, तो उत्तरार्द्ध पूर्व के बराबर होता है।

मान लें कि आप Model–View–Controller पैटर्न का उपयोग कर रहे हैं, here का सुझाव दिया गया है, आपका मॉडल एक सीपीयू का संचालन है। हालांकि यह एक अलग वर्ग हो सकता है, लेकिन मुझे कार्ड रीडर को एक अलग थ्रेड पर मॉडल करने का कोई कारण नहीं दिख रहा है। इसके बजाए, प्रोसेसर मॉडल में एक कार्ड रीडर मॉडल है जो java.util.Timer थ्रेड पर प्रतीक्षा करता है, मॉडल को टाइमर आग के रूप में अद्यतन करता है। अद्यतन मॉडल को ईडीटी को ईवेंट पोस्ट करने के सामान्य पाठ्यक्रम में दृश्य को सूचित करने दें। जेस्चर देखने के जवाब में नियंत्रक को कार्ड रीडर मॉडल को रद्द और शेड्यूल करने दें।

+0

एक तरफ, मुझे पसंद है कि आप प्रोग्राम को स्वचालित रूप से कैसे प्रस्तुत करते हैं, लेकिन आपको 'paintComponent() 'को ओवरराइड करना चाहिए। साथ ही, 'सारस्टविच विस्तारित करता है JToggleButton' आपके इवेंट हैंडलिंग को नाटकीय रूप से सरल बना देगा, जैसा कि यहां दिखाया गया है [http://sites.google.com/site/drjohnbmatthews/buttons)। – trashgod

+0

क्या आप www.jowsey.com से कुछ स्रोत कोड देख रहे हैं? यही एकमात्र चीज है जिसके बारे में मैं सोच सकता हूं। मैंने इसके लिए जीयूआई कोड नहीं लिखा; यह मेरे दोस्त द्वारा 12 या 13 साल पहले लिखा गया था। मैंने सीपीयू लिखा, और जीयूआई प्रोग्रामिंग सीखने के लिए हाल ही में इसे एक कार्ड रीडर और टेलीलेट टाइप करने के लिए प्रोजेक्ट में लौट आया। – Chap

+0

पीछे की ओर, मुझे लगता है कि आप थ्रेड के बजाय टाइमर का उपयोग करने के बारे में सही हैं। लेकिन चूंकि यह जीयूआई अवधारणाओं के लिए एक सीखने की परियोजना है, इसलिए मैं "नाटक" करना चाहता हूं कि पृष्ठभूमि धागे वास्तव में भारी काम कर रहे हैं, जिसे मैं जीयूआई प्रतिक्रिया बनाए रखने के लिए ऑफलोड कर रहा हूं। (मूल्यवान अवलोकनों के लिए +1।) – Chap

4

1) जीयूआई बनाने के लिए, खाली, या जावा पैकेज (रों) से मूलभूत मूल्यों के आधार पर होना चाहिए

2) शुरू periodic = new AccurateScheduledRunnable() {...};

periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, 
      TimeUnit.MINUTES); 

3) ScheduledFuture<?> periodicMonitor; के लिए मॉनिटर की घोषणा तो आप के लिए मिल उदाहरण ...

periodic = new AccurateScheduledRunnable() {...}; 

long she = periodicMonitor.getDelay(TimeUnit.SECONDS); 

4) SwingWorker-समय शेष 01 का उपयोग करके बहु सूत्रण का समर्थन कर सकता हैExecutor executor = Executors.newCachedThreadPool();, तो आप में सक्षम this one

5) जो कुछ भी आप की उम्मीद ...

संपादित

hmmmm AccurateScheduledRunnable कस्टम सार क्लास है

लेकिन मैं इस एक का निर्माण मेरी का आनंद के लिए, हो सकता है। उत्तर दें कि मैंने

enter image description here

के बारे में बात की
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.beans.*; 
import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.List; 
import java.util.concurrent.Executor; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.ScheduledFuture; 
import java.util.concurrent.TimeUnit; 
import javax.swing.*; 
import javax.swing.table.*; 

public class TableIcon extends JFrame implements Runnable { 

    private static final long serialVersionUID = 1L; 
    private JTable table; 
    private JLabel myLabel = new JLabel("waiting"); 
    private JLabel lastRunLabel = new JLabel("waiting"); 
    private int pHeight = 40; 
    private boolean runProcess = true; 
    private int count = 0; 
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 
    private ScheduledExecutorService scheduler; 
    private AccurateScheduledRunnable periodic; 
    private ScheduledFuture<?> periodicMonitor; 
    private Executor executor = Executors.newCachedThreadPool(); 
    private Date dateLast; 
    private Date dateNext; 
    private Date dateRun; 
    private int taskPeriod = 1; 
    private int dayCount = 0; 
    private int hourCount = 0; 
    private int minuteCount = 0; 
    private int secondCount = 0; 
    private Timer timerRun; 
    private int delay = 3000; 
    private boolean bolo = false; 

    public TableIcon() { 
     ImageIcon errorIcon = (ImageIcon) UIManager.getIcon("OptionPane.errorIcon"); 
     ImageIcon infoIcon = (ImageIcon) UIManager.getIcon("OptionPane.informationIcon"); 
     ImageIcon warnIcon = (ImageIcon) UIManager.getIcon("OptionPane.warningIcon"); 
     String[] columnNames = {"Picture", "Description"}; 
     Object[][] data = {{errorIcon, "About"}, {infoIcon, "Add"}, {warnIcon, "Copy"},}; 
     DefaultTableModel model = new DefaultTableModel(data, columnNames) { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public Class getColumnClass(int column) { 
       return getValueAt(0, column).getClass(); 
      } 
     }; 
     table = new JTable(model); 
     table.setRowHeight(pHeight); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     JScrollPane scrollPane = new JScrollPane(table); 
     add(scrollPane, BorderLayout.CENTER); 
     lastRunLabel.setPreferredSize(new Dimension(200, pHeight)); 
     lastRunLabel.setHorizontalAlignment(SwingConstants.CENTER); 
     add(lastRunLabel, BorderLayout.NORTH); 
     myLabel.setPreferredSize(new Dimension(200, pHeight)); 
     myLabel.setHorizontalAlignment(SwingConstants.CENTER); 
     add(myLabel, BorderLayout.SOUTH); 
     scheduler = Executors.newSingleThreadScheduledExecutor(); 
     periodic = new AccurateScheduledRunnable() { 

      private final int ALLOWED_TARDINESS = 200; 
      private int countRun = 0; 
      private int countCalled = 0; 

      @Override 
      public void run() { 
       countCalled++; 
       if (this.getExecutionTime() < ALLOWED_TARDINESS) { 
        countRun++; 
        executor.execute(new TableIcon.MyTask("GetCurrTime")); // non on EDT 
       } 
      } 
     }; 
     periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.MINUTES); 
     periodic.setThreadMonitor(periodicMonitor); 
     new Thread(this).start(); 
     prepareStartShedule(); 
    } 

    private void prepareStartShedule() { 
     timerRun = new javax.swing.Timer(delay, startCycle()); 
     timerRun.setRepeats(true); 
     timerRun.start(); 
    } 

    private Action startCycle() { 
     return new AbstractAction("Start Shedule") { 

      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       executor.execute(new TableIcon.MyTask("StartShedule")); // non on EDT 
      } 
     }; 
    } 

    private void changeTableValues() { 
     Runnable doRun = new Runnable() { 

      @Override 
      public void run() { 
       if (bolo) { 
        bolo = false; 
        table.getModel().setValueAt("*/*/*/**/*/*/*", 0, 1); 
        table.getModel().setValueAt(" k k k k k k k k", 1, 1); 
        table.getModel().setValueAt("@#@#@#@", 2, 1); 
       } else { 
        bolo = true; 
        table.getModel().setValueAt("Green Peper", 0, 1); 
        table.getModel().setValueAt("Yellow Apple", 1, 1); 
        table.getModel().setValueAt("Orange Bus", 2, 1); 
       } 
      } 
     }; 
     SwingUtilities.invokeLater(doRun); 
    } 

    private void distAppInfo() { 
     Runnable doRun = new Runnable() { 

      @Override 
      public void run() { 
       dateNext = new java.util.Date(); 
       dateLast = new java.util.Date(); 
       long tme = dateNext.getTime(); 
       tme += (taskPeriod * 60) * 1000; 
       dateNext.setTime(tme); 
       lastRunLabel.setText("Last : " + sdf.format(dateLast) + "/Next : " + sdf.format(dateNext)); 
      } 
     }; 
     SwingUtilities.invokeLater(doRun); 
    } 

    private void changeLabelColor() { 
     Runnable doRun = new Runnable() { 

      @Override 
      public void run() { 
       Color clr = lastRunLabel.getForeground(); 
       if (clr == Color.red) { 
        lastRunLabel.setForeground(Color.blue); 
       } else { 
        lastRunLabel.setForeground(Color.red); 
       } 
      } 
     }; 
     SwingUtilities.invokeLater(doRun); 
    } 

    @Override 
    public void run() { 
     while (runProcess) { 
      try { 
       Thread.sleep(5000); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
      executor.execute(new TableIcon.MyTask("ChangeIconLabel")); // non on EDT 
     } 
    } 

    private void setIconLabel() { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       String text = ""; 
       dateRun = new java.util.Date(); 
       long tme = dateRun.getTime(); 
       long she = periodicMonitor.getDelay(TimeUnit.SECONDS); 
       dayCount = (int) (she/(24 * 60 * 60)); 
       hourCount = (int) (she/(60 * 60)); 
       minuteCount = (int) (she/(60)); 
       secondCount = (int) she; 
       int hourss = hourCount; 
       int minutess = minuteCount; 
       if (dayCount > 0) { 
        hourCount -= (dayCount * 24); 
        minuteCount -= ((dayCount * 24 * 60) + (hourCount * 60)); 
        secondCount -= (minutess * 60); 
        //System.out.println(" Days : " + dayCount + " ,Hours : " + hourCount + " , Minutes : " + minuteCount + " , Seconds : " + secondCount); 
        text = (" " + dayCount + " Days " + hourCount + " h : " + minuteCount + " m : " + secondCount + " s"); 
       } else if (hourCount > 0) { 
        minuteCount -= ((hourss * 60)); 
        secondCount -= (minutess * 60); 
        //System.out.println(" Hours : " + hourCount + " , Minutes : " + minuteCount + " , Seconds : " + secondCount); 
        text = (" " + hourCount + " h : " + minuteCount + " m : " + secondCount + " s"); 
       } else if (minuteCount > 0) { 
        secondCount -= (minutess * 60); 
        //System.out.println(" Minutes : " + minuteCount + " , Seconds : " + secondCount); 
        text = (" " + minuteCount + " m : " + secondCount + " s"); 
       } else { 
        //System.out.println(" Seconds : " + secondCount); 
        text = (" " + secondCount + " s"); 
       } 
       tme += she * 1000; 
       ImageIcon myIcon = (ImageIcon) table.getModel().getValueAt(count, 0); 
       String lbl = "Row at : " + count + " Remains : " + text; 
       myLabel.setIcon(myIcon); 
       myLabel.setText(lbl); 
       count++; 
       if (count > 2) { 
        count = 0; 
       } 
      } 
     }); 
    } 

    public static void main(String[] args) { 
     TableIcon frame = new TableIcon(); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.setLocation(150, 150); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    private class MyTask extends SwingWorker<Void, Integer> { 

     private String str; 
     private String namePr; 

     MyTask(String str) { 
      this.str = str; 
      addPropertyChangeListener(new SwingWorkerCompletionWaiter(str, namePr)); 
     } 

     @Override 
     protected Void doInBackground() throws Exception { 
      if (str.equals("GetCurrTime")) { 
       distAppInfo(); 
      } else if (str.equals("ChangeIconLabel")) { 
       setIconLabel(); 
      } else if (str.equals("StartShedule")) { 
       changeTableValues(); 
      } 
      return null; 
     } 

     @Override 
     protected void process(List<Integer> progress) { 
      //System.out.println(str + " " + progress.get(progress.size() - 1)); 
     } 

     @Override 
     protected void done() { 
      if (str.equals("GetCurrTime")) { 
       changeLabelColor(); 
      } else if (str.equals("ChangeIconLabel")) { 
       //setIconLabel(); 
      } else if (str.equals("StartShedule")) { 
       //changeTableValues(); 
      } 
     } 
    } 

    private class SwingWorkerCompletionWaiter implements PropertyChangeListener { 

     private String str; 
     private String namePr; 

     SwingWorkerCompletionWaiter(String str, String namePr) { 
      this.str = str; 
      this.namePr = namePr; 
     } 

     SwingWorkerCompletionWaiter(String namePr) { 
      this.namePr = namePr; 
     } 

     @Override 
     public void propertyChange(PropertyChangeEvent event) { 
      if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { 
       System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) { 
       System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) { 
       System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); 
      } else { 
       System.out.println("SomeThing Wrong happends with Thread Status with Name :" + str); 
      } 
     } 
    } 
} 

abstract class AccurateScheduledRunnable implements Runnable { 

    private ScheduledFuture<?> thisThreadsMonitor; 

    public void setThreadMonitor(ScheduledFuture<?> monitor) { 
     this.thisThreadsMonitor = monitor; 
    } 

    protected long getExecutionTime() { 
     long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS); 
     return delay; 
    } 
} 
+0

+1। अफसोस की बात है, मौजूदा [स्रोत] (http://www.jowsey.com/java/sim1620/) गलत तरीके से सिंक्रनाइज़ किया गया है, बिना किसी साधारण फिक्स के। अगर मैं पूछूं, तो 'सटीक शेड्यूलर रुनबल' क्या है? – trashgod

+0

@trashgod कृपया मेरे 'सटीक शेड्यूल्डरनेबल' – mKorbel

+0

उत्कृष्ट देखें। एक तरफ के रूप में, 'UIManager.getIcon() '' Icon' देता है, न कि' ImageIcon', जो 'एक्वा' पर 'क्लासकास्ट अपवाद' फेंकता है। 'आइकन त्रुटि Icon = UIManager.getIcon (" ... ")' पोर्टेबल काम करता प्रतीत होता है। – trashgod

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