2012-05-18 15 views
7

पर ऑब्जेक्ट संदर्भ पास करने वाले एकाधिक थ्रेड्स मैं जावा में बस शुरुआत कर रहा हूं और बहु-थ्रेडेड अनुप्रयोगों पर ठोकर खा रहा हूं। मुझे पता है कि यह प्रश्न यहां कुछ पोस्ट के समान है लेकिन मुझे अपनी क्वेरी के लिए बेहतर उत्तर नहीं मिला। असल में, मैं किसी ऑब्जेक्ट को एक स्थिर विधि में पास करना चाहता हूं और विधि ऑब्जेक्ट के मानों/गुणों के आधार पर केवल आउटपुट लौटाएगी। प्रत्येक कॉल के लिए, मैं ऑब्जेक्ट का एक नया उदाहरण बना रहा हूं और इस तरीके के अंदर ऑब्जेक्ट को संशोधित करने का कोई मौका नहीं है। अब, मेरा सवाल यह है कि, क्या JVM कई थ्रेड द्वारा प्रत्येक कॉल के लिए स्टैक में स्थिर विधि और उसके स्थानीय चर का एक नया उदाहरण बना देगा (ऑब्जेक्ट को छोड़कर यह ढेर पर होगा)? मैं क्या हासिल करना चाहते का एक स्पष्ट विचार के लिए, यहाँ मेरी कोड है:स्टैटिक हेल्पर विधि

TestConcurrent.java

import classes.Player; 

public class TestConcurrent 
{ 
    private static int method(Player player) 
    { 
     int y = (player.getPoints() * 10) + 1; 

      try { 
        Thread.sleep(1000); 
      } catch (InterruptedException e) {} 

      return ++y; 
    } 

    public static void main(String[] args) throws Exception 
    { 
     // Create 100 threads 
     for(int i=1;i<=100;i++) 
     { 
      final int j = i; 
      // Create a new Thread 
      new Thread() 
      { 
       public void run() 
       { 
        // Create a new instance of the Player class 
        Player player = new Player(j,j,"FirstName" + j, "LastName" + j); 
        // Call static method() and pass a new instance of Player class 
        System.out.println("Thread " + j + ": " + TestConcurrent.method(player)); 
        // Check the values of the Player class after the call to the static method() 
        System.out.println("Player" + player.getAcctId() + " : Points=" + player.getPoints() + " Name=" + player.getFirstName() + " " + player.getLastName()); 
       } 
      }.start(); 
     } 
    } 

} 

Player.java

package classes; 

public class Player 
{ 
    private int acctId, points; 
    String firstName, lastName; 

    public Player(int acctId, int points, String firstName, String lastName) 
    { 
     this.acctId = acctId; 
     this.points = points; 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 

    public int getAcctId() { 
     return acctId; 
    } 
    public void setAcctId(int acctId) { 
     this.acctId = acctId; 
    } 
    public int getPoints() { 
     return points; 
    } 
    public void setPoints(int points) { 
     this.points = points; 
    } 
    public String getFirstName() { 
     return firstName; 
    } 
    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 
    public String getLastName() { 
     return lastName; 
    } 
    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 
} 

उत्पादन:

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

Thread 2: 22 
Player8 : Points=8 Name=FirstName8 LastName8 
Thread 22: 222 
Thread 26: 262 
Thread 23: 232 
Player23 : Points=23 Name=FirstName23 LastName23 
Thread 21: 212 
Player21 : Points=21 Name=FirstName21 LastName21 
Thread 25: 252 
Player25 : Points=25 Name=FirstName25 LastName25 
Thread 20: 202 
Thread 19: 192 
Thread 24: 242 
Player24 : Points=24 Name=FirstName24 LastName24 
Player9 : Points=9 Name=FirstName9 LastName9 
Thread 28: 282 
+1

+1 - महान पहला सवाल! StackOverflow में आपका स्वागत है! – jmort253

उत्तर

4

स्थिर विधि और उसके स्थानीय का एक नया उदाहरण बनाने JVM होगा कई थ्रेड द्वारा प्रत्येक कॉल के लिए स्टैक में चर (ऑब्जेक्ट को छोड़कर यह ढेर पर होगा)?

हाँ, यह बिल्कुल सही है।

यदि एक स्थिर विधि केवल स्थानीय चर को संदर्भित करती है, तो यह स्वचालित रूप से थ्रेड सुरक्षित है। (वास्तव में, यह गैर स्थैतिक तरीकों के लिए भी है।)

आम तौर पर हालांकि, मैं कहूंगा कि यदि संभव हो तो आपको static से बचना चाहिए। आम तौर पर यह इस तथ्य के कारण कोड को कठिन और कारण बनाने के लिए कठिन बनाता है कि स्थिर सदस्य वैश्विक रूप से एक अर्थ में हैं।

+0

'स्थिर 'विधियां पूरी तरह से ठीक और उपयोग करने के लिए उचित हैं। उदाहरण के लिए 'Math.min'। तो 'Math.PI' जैसे स्थिरांक हैं। केवल गैर-अंतिम 'स्थैतिक' चर से बचें, वे सभी प्रकार की बहुप्रणाली त्रुटियों का कारण बनते हैं। बहुत तेज प्रतिक्रिया के लिए –

+0

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

+0

@PopoyMakisig, यह जवाब देने के लिए वास्तव में एक कठिन सवाल है। मैंने एक बार एक केंद्रीय वर्ग 'सर्वर' के साथ एक गेम लिखा था जिसे मुझे यहां और वहां उपयोगी सामग्री करने के लिए सभी जगहों पर पारित करना पड़ा था। मैं तंग आ गया और स्थैतिक तरीकों का निर्माण किया। सबसे पहले यह एक महान सरलीकरण की तरह लग रहा था, लेकिन अंत में मैंने निर्णय को खेद व्यक्त किया और वापस कर दिया। अगर मैं तुम थे, तो मैं कोशिश करूँगा, देखें कि यह कैसे काम करता है। यदि यह नौकरी करता है तो इससे खुश रहें, अगर आप इसे वापस लेते हैं तो इसे एक सबक के रूप में लें :-) – aioobe

4

static विधियां कोई समस्या नहीं है, केवल static चर धागे भर में साझा किए जाएंगे।

तो दो धागे

public static int sum(int a, int b) { 
    int tmp = a + b; 
    return tmp; 
} 

लागू समस्याओं में नहीं चलेंगे।

static int tmp; 

public static int sum(int a, int b) { 
    tmp = a + b; 
    return tmp; 
} 

, मल्टी-थ्रेडेड असफल क्योंकि एक धागा दूसरे के ऊपर लिख सकता है tmp मूल्य होगा।

स्थानीय चर, यहां तक ​​कि static विधियों में भी स्थानीय और इस प्रकार सुरक्षित हैं।

static विधियों का उपयोग करना अच्छा है। यह हाइलाइट करता है कि विधि को ऑब्जेक्ट चरों तक पहुंच की आवश्यकता नहीं है।static गैर-निरंतर चर का उपयोग त्रुटियों से ग्रस्त है, इसे हर कीमत से बचें (और चर को एक्सेस करने की आवश्यकता होने पर निरंतर सिंक्रनाइज़ेशन का उपयोग करें)।

+0

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

+0

आपने अभी इस वाक्य के साथ अपना जीवन बचाया है: "स्थाई विधियों में भी स्थानीय चर, अभी भी स्थानीय हैं और इस प्रकार सुरक्षित हैं।" मैं इस जवाब पर हैरान हूँ। यह सहजता से गलत लगता है, लेकिन शुक्रिया का शुक्र है, यह नहीं है! – aliteralmind

+0

जब किसी ने कंपाइलर्स के साथ काम किया है तो यह काफी स्पष्ट होना चाहिए। स्थानीय चर '' स्टैक 'पर संग्रहीत हैं; और चूंकि प्रत्येक थ्रेड के पास अपने स्वयं के ढेर होते हैं, इसलिए वे एक दूसरे को स्थानीय चर नहीं देख सकते हैं। वास्तव में, वे वर्तमान स्टैक पॉइंटर से संबंधित हैं, इसलिए एक ही स्टैक पर भी कई प्रतियां हो सकती हैं। अन्यथा, रिकर्सन ठीक से काम नहीं करेगा। –