2012-05-18 7 views
7

Sono solo un principiante in Java e sono incappato in applicazioni multi-thread. So che questa domanda è simile ad alcuni post qui, ma non ho trovato una risposta migliore per la mia richiesta. Fondamentalmente, voglio passare un oggetto a un metodo statico e il metodo restituirà solo un output basato sui valori/proprietà dell'oggetto. Per ogni chiamata, sto creando una nuova istanza dell'oggetto e non c'è alcuna possibilità che io modifichi l'oggetto all'interno del metodo. Ora, la mia domanda è, JVM creerà una nuova istanza del metodo statico e le sue variabili locali nello Stack (escludendo l'oggetto come sarà nell'Heap) per ogni chiamata da più thread? Per una visione chiara di ciò che voglio raggiungere, qui è il mio codice:Più thread che passano un riferimento di oggetto al metodo di supporto statico

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; 
    } 
} 

USCITA:

Poiché non ho inserito una parola chiave sincronizzata, L'output sarà diverso ogni volta ed è simile al seguente: (l'output è corretto ed è esattamente quello che mi aspetto, voglio solo chiarire che sono sulla strada giusta dal momento che non voglio usare la sincronizzazione come sarà rallentare il processo perché ogni thread dovrà attendere che l'altro filo per terminare prima di chiamare il metodo statico)

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 - Ottima prima domanda! Benvenuto in StackOverflow! – jmort253

risposta

4

sarà JVM creare una nuova istanza del metodo statico e il suo locale variabili nello Stack (escluso l'oggetto così come sarà nell'Heap) per ogni chiamata da più thread?

Sì, è esattamente giusto.

Se un metodo statico fa riferimento solo a variabili locali, è automaticamente thread-safe. (In effetti, questo vale anche per i metodi non statici.)

In generale, tuttavia, direi che dovresti evitare static se possibile. In generale rende il codice più difficile da testare e ragionare a causa del fatto che i membri statici sono in un certo senso globali.

+0

I metodi 'static' sono perfettamente validi e ragionevoli da usare. Ad esempio 'Math.min'. Quindi sono costanti come 'Math.PI'. Evita solo variabili 'static' non definitive, causano tutti i tipi di errori di multithreadingness. –

+0

grazie per la risposta molto veloce. questo è in realtà ciò che voglio raggiungere. Voglio che il metodo di supporto agisca come un metodo globale che qualsiasi thread può chiamare in qualsiasi momento. il mio progetto iniziale era in realtà il metodo è all'interno di una classe normale e quindi ogni thread creerà un'istanza della classe e quindi chiamerà il metodo. il mio metodo statico attuale ha un sacco di logica in corso e sono preoccupato per le prestazioni ogni volta che ne creo una nuova istanza. ma come ho dimostrato sopra, il metodo non modificherà l'oggetto passato ad esso. sarà meglio se continuo così, usando metodi statici? –

+0

@PopoyMakisig, è una domanda davvero difficile a cui rispondere. Una volta scrissi un gioco con un 'Server' di classe abbastanza centrale che dovevo girare dappertutto per fare cose utili qua e là. Mi sono stufato e ho creato metodi statici. All'inizio sembrava una grande semplificazione, ma alla fine ho deplorato la decisione e sono tornato. Se fossi in te, proverei, vedi come ha funzionato. Sii felice con lui se fa il lavoro, prendilo come una lezione se finisci di tornare :-) – aioobe

4

static metodi non sono un problema, solo le variabili static saranno condivise tra thread.

Quindi due thread invocando

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

non incorrere in problemi.

static int tmp; 

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

fallirà multi-thread, perché un thread può sovrascrivere anothers tmp valore.

Le variabili locali, anche nei metodi static, sono ancora locali e quindi sicure.

Utilizzare i metodi static è buono. Evidenzia che il metodo non richiede l'accesso alle variabili oggetto.L'utilizzo delle variabili non costanti static è soggetto a errori, evitarlo a tutti i costi (e utilizzare la sincronizzazione su una costante se è necessario accedere alla variabile).

+0

ai fini della mia applicazione, non userò alcuna variabile statica non costante. sto usando solo variabili statiche finali se ho bisogno di costanti definite. quindi tutto è semplice al momento. Userò metodi di sincronizzazione e/o istanza quando la funzione di concorrenza di Java è già molto chiara per me. grazie per la tua risposta. –

+0

Mi hai appena salvato la vita con questa frase: "Le variabili locali, anche in metodi statici, sono ancora locali e quindi sicure." Sono sorpreso di questa risposta. Sembra intuitivamente sbagliato, ma grazie a Dio non lo è! – aliteralmind

+0

Dovrebbe essere abbastanza ovvio quando si lavora con i compilatori. Le variabili locali sono memorizzate nello '' stack ''; e poiché ogni thread ha necessariamente il proprio stack, non possono vedere le altre variabili locali. Infatti, sono indirizzati rispetto al puntatore dello stack corrente, quindi potrebbero esserci più copie sullo stesso stack. Altrimenti, la ricorsione non funzionerebbe correttamente neanche. –

Problemi correlati