2015-10-01 14 views
5

Attualmente sto lavorando per comprendere il concetto Java del multithreading. Ho seguito un tutorial che utilizza l'esempio Tortoise and the Hare per spiegare il concetto di multithreading e in larga misura ho compreso la sintassi e la logica dell'esercitazione video. Alla fine del video tutorial, Youtuber ha dato un compito che implica l'applicazione del multithreading su una pista olimpionica.Altri thread si interrompe quando un thread raggiunge la destinazione

Utilizzando il mio knowledege dell'esempio, sono riuscito a creare 10 thread (che rappresentano gli atleti) che vengono eseguiti all'interno di un ciclo, che esegue 100 volte (che rappresentano 100 metri).

La mia sfida è che quando lo schedulatore di thread fa un atleta per arrivare a 100 metri prima degli altri 9 atleti, i rimanenti 9 fili non completano la loro corsa. Questo di solito non è il caso in una pista standard. Il fatto che un Thread chiamato Usain Bolts arrivi a 100 prima, non significa che Yohan Blake dovrebbe smettere di correre se è a 90m in quel momento.

Sono anche interessato a ottenere la distanza (si noti che tutti utilizzano la stessa variabile) per ogni thread, in modo che io possa utilizzare una funzione per restituire le posizioni di ogni Thread alla fine della gara.

Quello che ho fatto (che non funzionava): 1) Ho provato ad utilizzare un if else (contenente nove "altro" economico) per assegnare la distanza di ogni filo di esecuzione di una nuova variabile intera. (usando la proprietà Thread.currentThread(). getName() e il nome di ciascun thread) ma non ha funzionato bene per me. Questo è stato un tentativo di dare posizioni agli atleti da solo usando la loro distanza ma non fa nulla per i 9 atleti che non finiscono la gara.
2) Ho anche provato ad usare un ArrayList per popolare la distanza in fase di esecuzione ma per alcuni strani motivi questo sovrascrive ancora la distanza ogni volta che vuole aggiungere un'altra distanza.

Qui di seguito sono i miei codici:

package olympics100meters; 

import java.util.ArrayList; 

public class HundredMetersTrackRules implements Runnable { 
public static String winner; 

public void race() { 
for (int distance=1;distance<=50;distance++) { 
System.out.println("Distance covered by "+Thread.currentThread ().getName ()+" is "+distance+" meters."); 


boolean isRaceWon=this.isRaceWon(distance); 
if (isRaceWon) { 
ArrayList<Integer> numbers = new ArrayList(); 
numbers.add(distance); 
System.out.println("testing..."+numbers); 
break; 
} 

} 
} 


private boolean isRaceWon(int totalDistanceCovered) { 
    boolean isRaceWon=false; 
    if ((HundredMetersTrackRules.winner==null)&& (totalDistanceCovered==50)) { 
    String winnerName=Thread.currentThread().getName(); 
    HundredMetersTrackRules.winner=winnerName; 
    System.out.println("The winner is "+HundredMetersTrackRules.winner); 
    isRaceWon=true; 
    } 

    else if (HundredMetersTrackRules.winner==null) { 
    isRaceWon=false; 
    } 

    else if (HundredMetersTrackRules.winner!=null) { 
    isRaceWon=true; 
    } 
    return isRaceWon; 
} 

public void run() { 
this.race(); 
}  
} 

Questo è il mio metodo main (ho ridotto a 5 atleti finché non risolvere i problemi):

public class Olympics100Meters { 

/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    HundredMetersTrackRules racer=new HundredMetersTrackRules(); 
    Thread UsainBoltThread=new Thread(racer,"UsainBolt"); 
    Thread TysonGayThread=new Thread (racer,"TysonGay"); 
    Thread AsafaPowellThread=new Thread(racer,"AsafaPowell"); 
    Thread YohanBlakeThread=new Thread (racer,"YohanBlake"); 
    Thread JustinGatlinThread=new Thread (racer,"JustinGatlin"); 

    UsainBoltThread.start(); 
    TysonGayThread.start(); 
    AsafaPowellThread.start(); 
    YohanBlakeThread.start(); 
    JustinGatlinThread.start(); 

} 
} 
+0

L'elenco delle matrici non è sicuro per i thread. Non vedo la parola chiave sincronizzata normalmente usata per la concorrenza ... Non sto mostrando come stai gestendo la razza a parte l'arraylist forse usa il blockingqueue o qualcosa che è sicuro o usa il lavoro chiave sincronizzato –

+2

Se vuoi scrivere flessibile e robusto codice multi-threading, dovresti assolutamente evitare di affrontare direttamente la classe Thread. Usa Runnable per definire i tuoi compiti e falli eseguire tramite un ExecutorService. Sarai quindi in grado di controllare il flusso di esecuzione e le condizioni di arresto. Esistono numerosi esempi di usi ExecutorService in rete. – devlearn

+0

Grazie. Ma c'è un modo per far sì che questo programma faccia ciò che voglio facendo usando direttamente la classe Thread? Voglio essere sicuro dei concetti fondamentali nel multithreading. –

risposta

0
  1. La mia sfida è che ... i restanti 9 thread non completano la loro corsa.

Ciò è causato da isRaceWon() implementazione del metodo. Lo controlli ad ogni metro per ogni corridore. Non appena il primo corridore raggiunge a 100 metri, il break si chiama il prossimo passo di ogni loop corridore (la gara è vinta per ogni ciclo

btw, ha senso utilizzare volatile statuc String per il nome del vincitore, per evitare di modello di memoria di Java ambiguità.

  1. sono interessato a ottenere la distanza ... per ogni thread, in modo che possa utilizzare una funzione per restituire le posizioni di ciascun thread alla fine anche della gara.

Se l'obiettivo finale è quello di ottenere la posizione, creare un campo di classe public List<String> finishingOrder = new ArrayList<String> e un metodo finish

private synchronized finish() { 
    finishingOrder.add(Thread.currentThread().getName()) 
} 

e chiamarlo dopo il "run" loop

no dimentica di chiamare join() per tutti i thread di runner nel tuo main. Successivamente, lo finishingOrder conterrà i nomi in ordine di finitura.

0

Il frammento di codice qui sotto sta causando isRaceWon per tornare vero per ogni istanza di HundredMetersTrackRules non appena il winner campo condiviso è impostato su non nullo (cioè qualcuno vince.):

else if (HundredMetersTrackRules.winner!=null) { 
    isRaceWon=true; 
} 

Questo a turn fa in modo che il loop di race() si interrompa per ogni istanza del tuo Runnable. Il metodo run() termina, terminando la discussione.

Il problema è solo un errore logico e non specifico per il threading. Tuttavia, come già menzionato da altri utenti, esistono alcune best practice di threading che è possibile adottare anche in questo codice, ad esempio l'utilizzo di volatile per i campi condivisi dai thread.

Problemi correlati