2009-07-05 13 views
14

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

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

/************************************************************************ 
    Original code in Deitel book with linear search of selected Radio button in Actionlistener 
    ****************************************************************************/ 
    import java.awt.Color; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.ButtonGroup; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JRadioButtonMenuItem; 


public class MenuTest extends JFrame{ 
    private final Color colorValues[] = {Color.BLACK, Color.WHITE, Color.GREEN}; 
    private JRadioButtonMenuItem colorItems[];  
    private ButtonGroup colorButtonGroup; 


    public MenuTest(){ 
     super("Menu Test"); 
     JMenu fileMenu = new JMenu("File"); 

     JMenuBar bar = new JMenuBar(); 
     setJMenuBar(bar); 
     bar.add(fileMenu); 

     String colors[] = {"Black", "White", "Green"}; 
     JMenu colorMenu = new JMenu("Color"); 
     colorItems = new JRadioButtonMenuItem[colors.length]; 
     colorButtonGroup = new ButtonGroup(); 

     ItemHandler itemHandler = new ItemHandler(); 

     for(int count = 0; count < colors.length; count++){ 
      colorItems[count] = new JRadioButtonMenuItem(colors[count]); 
      colorMenu.add(colorItems[count]); 
      colorButtonGroup.add(colorItems[count]); 
      colorItems[count].addActionListener(itemHandler); 
     } 

     colorItems[0].setSelected(true); 
     fileMenu.add(colorMenu); 
     fileMenu.addSeparator(); 

    } 

    private class ItemHandler implements ActionListener{ 
     public void actionPerformed(ActionEvent event){ 
      for(int count = 0; count < colorItems.length; count++){ 
       if(colorItems[count].isSelected()){ 
        getContentPane().setBackground(colorValues[count]); 
       } 
      } 
     } 
    } 


    public static void main(String args[]){ 
     MenuTest menuFrame = new MenuTest(); 
     menuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     menuFrame.setSize(600,400); 
     menuFrame.setVisible(true); 
     menuFrame.getContentPane().setBackground(menuFrame.colorValues[0]); 
    } 
} 
    /************************************************************************ 
    My Code redefined version of Deitel's w/o linear search in ActionListener 
    ************************************************************************/ 

     import java.awt.Color; 
     import java.awt.event.ActionEvent; 
     import java.awt.event.ActionListener; 

     import javax.swing.ButtonGroup; 
     import javax.swing.JFrame; 
     import javax.swing.JLabel; 
     import javax.swing.JMenu; 
     import javax.swing.JMenuBar; 
     import javax.swing.JMenuItem; 
     import javax.swing.JRadioButtonMenuItem; 

     public class MenuTest extends JFrame{ 
     private final Color colorValues[] = {Color.BLACK, Color.WHITE, Color.GREEN}; 
     private JRadioButtonMenuItem colorItems[];  
     private ButtonGroup colorButtonGroup; 


     public MenuTest(){ 
      super("Menu Test"); 
      JMenu fileMenu = new JMenu("File"); 

      JMenuBar bar = new JMenuBar(); 
      setJMenuBar(bar); 
      bar.add(fileMenu); 

      String colors[] = {"Black", "White", "Green"}; 
      JMenu colorMenu = new JMenu("Color"); 
      colorItems = new JRadioButtonMenuItem[colors.length]; 
      colorButtonGroup = new ButtonGroup(); 

      ItemHandler itemHandler = new ItemHandler(); 

      for(int count = 0; count < colors.length; count++){ 
       colorItems[count] = new JRadioButtonMenuItem(colors[count]); 
       colorMenu.add(colorItems[count]); 
       colorButtonGroup.add(colorItems[count]); 
       colorItems[count].addActionListener(new ItemHandler(colorValues[count])); 
      } 

      colorItems[0].setSelected(true); 
      fileMenu.add(colorMenu); 
      fileMenu.addSeparator(); 

     } 

     private class ItemHandler implements ActionListener{ 
      private Color setColor; 
      public ItemHandler(Color inColor){ 
       super(); 
       setColor = inColor; 
      } 
      public void actionPerformed(ActionEvent event){ 
       getContentPane().setBackground(setColor); 
       repaint(); 
      } 
     } 
     public static void main(String args[]){ 
      MenuTest menuFrame = new MenuTest(); 
      menuFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      menuFrame.setSize(600,400); 
      menuFrame.setVisible(true); 
      menuFrame.getContentPane().setBackground(menuFrame.colorValues[0]); 
     } 
    } 

उत्तर

17

सीपीयू उपयोग: किसी के नजदीक नहीं। श्रोताओं को केवल तभी बुलाया जाता है जब वे वस्तु की स्थिति बदलते हैं। वे वास्तव में "सुनो" नहीं करते हैं। जिस वस्तु को वे सुन रहे हैं, उन्हें आवश्यकता होने पर उन्हें कॉल किया जाता है। (नोट: यह एक सरलीकरण है)

मेमोरी उपयोग: अधिकतर एक एक्शनलिस्टर के पास कोई राज्य नहीं है। तो कुल स्थायी स्मृति उपयोग किसी ऑब्जेक्ट के लिए न्यूनतम आवश्यक है। आपके उदाहरण में, राज्य है, क्योंकि आपके पास सेटकॉलर फ़ील्ड है। लेकिन स्मृति उपयोग कम है।

आईएमओ, श्रोताओं कुशल हैं और आप जितना चाहें उतना उपयोग कर सकते हैं।

4

श्रोताओं को उन घटकों की तुलना में बहुत कम लागत है जो वे जुड़े हुए हैं। बस सैकड़ों श्रोताओं को सीपीयू या मेमोरी में बहुत अंतर करने की संभावना नहीं है। हालांकि, कुल कार्य श्रोताओं को और अधिक महत्वपूर्ण है। यदि आपको कोई प्रदर्शन समस्या दिखाई देती है, तो आप कारण को पहचानने और अनुकूलित करने के लिए एक CPU/मेमोरी प्रोफाइलर का उपयोग कर सकते हैं। ऐसा कुछ नहीं है जिसके बारे में आपको बहुत ज्यादा चिंता करने की ज़रूरत है।

1

ध्यान रखें कि सुनने व्यस्त प्रतीक्षा के समान नहीं है। श्रोता कुछ प्रकार के प्रॉक्सी तरीकों के माध्यम से इच्छुक पार्टियों की सूची में पंजीकृत है। अधिकांश श्रोता पैटर्न में बहुत कम बर्बाद CPU समय है।

1

कम कक्षाओं का उपयोग करने के लिए जावा एमई में एक परंपरा है, क्योंकि एक और कक्षा फ़ाइल डाउनलोड करने के ऊपरी हिस्से में महत्वपूर्ण है, इसलिए आपको कभी-कभी जावा कोड मिलता है जो श्रोता प्रकारों की संख्या को कम करता है और कम करता है, और श्रोता में सशर्त तर्क का उपयोग करता है। डेस्कटॉप जावा एप्लिकेशन आकार के लिए वास्तव में कोई समस्या नहीं है, लेकिन आप कभी-कभी इसे उस स्थान पर लीक करते देखते हैं।

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

मैं अज्ञात श्रोताओं का उपयोग करता हूं, क्योंकि ज्यादातर समय वे नामकरण परेशान करने के लिए बहुत आसान होते हैं।

दिखाया गया कोड क्रिया श्रोताओं का पता लगाने के लिए करता है कि मेनू आइटम 'कार्रवाई' किए गए हैं या नहीं।

निर्माता में यह चयनित मेनू आइटम सेट करता है, फिर मुख्य विधि में यह ऑब्जेक्ट के colorValues फ़ील्ड तक पहुंचता है, और पृष्ठभूमि का मान सेट करता है। जाहिर है यह व्यवहार छिपाने या encapsulating दोनों जानकारी में विफल रहता है।

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

for (int count = 0; count < colors.length; count++){ 
    colorItems[count] = new JRadioButtonMenuItem(colors[count]); 
    colorMenu.add(colorItems[count]); 
    colorButtonGroup.add(colorItems[count]); 

    final Color color = colorValues[count]; 

    colorItems[count].addChangeListener (new ChangeListener() { 
     public void stateChanged (ChangeEvent event){ 
      if (((AbstractButton) event.getSource()).isSelected()) 
       getContentPane().setBackground (color); 
     } 
    }); 
} 

colorItems[0].setSelected(true); 

// no call to setBackgroundColour() in main() 

तुम भी एक दूसरे फाइनल चर colorItem पकड़ और event.getSource() पर डाली से बचने के लिए हो सकता है।

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

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

0

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

someObject.addListener(new someAnonymousListener{ ... }); 

अनिवार्य होगा:

someListenerList.add(new someAnonymousListener{ ... }); 

अब तक, कोई नुकसान नहीं बेईमानी से। ऑब्जेक्ट बस अन्य सभी पंजीकृत श्रोताओं के साथ एक सूची में बैठा है।

हालांकि

, नोटिस क्या जब एक घटना वस्तु पर शुरू हो रहा है होता है:

for (SomeListener l : someListenerList) { 
    l.doSomeAction(); 
} 

ओह। यह वह जगह है जहां आपको सावधान रहना चाहिए। सुनिश्चित करें कि आपका श्रोता कुछ भी जटिल नहीं कर रहा है या आपको एक बाधा दिखाई देगी, जो प्रोफाइलिंग के दौरान दिखाई देगी।

नीचे पंक्ति: बस किसी ऑब्जेक्ट पर श्रोता धारण करना लगभग निःशुल्क है। बस सुनिश्चित करें कि आप बहुत से श्रोताओं को पंजीकृत नहीं कर रहे हैं, और उनमें से प्रत्येक अपने कार्यों को सरल और बिंदु पर रख रहा है।

+0

आप एक अच्छा मुद्दे को उठाने: श्रोताओं आम तौर पर बहुत कम करना चाहिए। अगर उन्हें कुछ जटिल करने की ज़रूरत है, तो उन्हें स्विंगवर्कर वर्ग का उपयोग करके आदर्श रूप से एक नया धागा बनाना चाहिए, फिर तुरंत लौटना चाहिए। –

4

यहां जितना बड़ा मुद्दा स्थापित किया गया है, और कुछ हद तक स्थायी पीढ़ी की स्मृति।

वास्तविक वस्तु आकार के लिए आप एक लिफाफा प्रभाव विश्लेषण का एक पीठ कर सकते हैं। एक वस्तु के बारे में 20 बाइट्स। मान लें कि आपके पास 10,000 हैं, यह 200K है। एक 1 जीबी मशीन पर जो 0.02% आपकी मशीन मेमोरी श्रोताओं पर जा रही है - मैं इसके बारे में किसी सेल फोन में चिंता नहीं करता।

ते बड़ी तस्वीर यह है कि आप कितनी कक्षाएं लोड करते हैं। मेरा प्रयोग (यूज़नेट पर कहीं भी) प्रत्येक अपेक्षाकृत छोटे अज्ञात आंतरिक वर्ग के लिए लगभग 2K ओवरहेड दिया गया। उनमें से 10,000 20 एमबी है। हमारी 1 जीबी मशीन का 2%। मैं इसके बारे में व्यापक रूप से वितरित सॉफ़्टवेयर के लिए चिंता करता हूं, लेकिन मध्यम आकार की कंपनी या विभाग में कुछ दर्जन मशीनों के लिए नहीं। फिर भी, यह वास्तव में काम करता है और रखरखाव योग्य सॉफ्टवेयर प्राप्त करने के लिए और अधिक महत्वपूर्ण है (जाहिर है, 85% सॉफ्टवेयर विकास लागत रखरखाव में है (कुछ परिभाषाओं के लिए) और अधिकांश परियोजनाएं अब तक कभी नहीं मिलती हैं)।

लोड कोड प्राप्त करना अपेक्षाकृत महंगा ऑपरेशन है। हालांकि सौभाग्य से अब हमारे पास प्रत्येक वर्ग फ़ाइल के लिए एक HTTP 1.0 अनुरोध करने के लिए एक नया सॉकेट खोलने के बजाय जार हैं (एप्लेट शुरू होने में धीमे थे - यह कैसे हुआ?)। फिर भी, तारों को देखा जाना चाहिए, विधि हल हो गई है, बाइटकोड सत्यापित, इत्यादि। और कंपाइलर की कीमत लेने से पहले इसे अभी भी 1,500 पुनरावृत्तियों के लिए व्याख्या किया जा रहा है।

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

तो, हमारे लिए, हम सेट अप समय को कम करना चाहते हैं, लेकिन हम घटना समय पर काफी अक्षम हो सकते हैं। 50 एमएमएस प्रतिक्रिया समय है जिसे हमें लक्षित करना चाहिए, और यह 1GHz मशीन पर 20,000,000 चक्र (बहुत!) है। तो एक उचित प्रदर्शन रणनीति कुछ प्रकार के श्रोता का उपयोग करना है। मॉडल की उचित मात्रा सुनने के लिए एक श्रोता प्रकार (संभवतः उदाहरण) का उपयोग करें। घटना तर्कों को अनदेखा करें (आमतौर पर राज्य परिवर्तन श्रोता के लिए एक अच्छा विचार) और यह जांचने के माध्यम से चलाएं कि क्या करने की आवश्यकता है (याद रखें कि हमारे पास बहुत समय है)।

मुझे अपने आप को दोहराने की आवश्यकता महसूस होती है। अपना कोड अच्छा बनाएं। कई इनपुट श्रोताओं (और आदेश) के लिए जाओ। राज्य परिवर्तन श्रोताओं को उनके तर्कों को अनदेखा करना चाहिए।

+0

10,000 ऑब्जेक्ट्स @ 20 बाइट्स! = 20 के (200 के होना चाहिए)। –

+0

@ केविन ब्रॉक एर्म, हाँ। डी 'ओह। 0.02%। –

2

मैं 5 साल से स्विंग प्रोग्रामर हूं। मेरे अनुभव के अनुसार, यह कभी भी कोई मुद्दा नहीं है कि श्रोताओं कैसे हो सकते हैं। श्रोताओं को अपमानित करना महत्वपूर्ण है जब वे घटनाओं में अधिक रुचि नहीं रखते हैं।

बस याद रखें कि जीयूआई अनुप्रयोगों में, प्रतिक्रिया समय स्मृति की तुलना में अधिक महत्वपूर्ण है। आप मेरे लेख में रुचि हो सकती:

Use Weak Listeners to avoid Memory Leaks
Know when your Object gets Garbage Collected
Long-Lived Models may cause Memory Leaks

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