0

Because I have a thread and in my main program I want to create multiple threads of the same thing and I don't want the same name I tried to create unique names for each thread, e.g Player_1, Player_2, etc.

The thing is that it throws Duplicate local variable which I know that is because I use the same variable but I don't know how else I can create multiple names for a thread without me writing them. Here is the code.

Original Question

for (int l=0; l < noPlayers; l++){
    String name = P + "" + (l + 1);
    System.out.println(name);
    Player name = new Player(TURN);
}

*The Player is the thread which extends and TURN is just a variable that will be processed.

Updated Question

   import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;

class Referee extends Thread{


}

class Player extends Thread{
    private int TURN;
    public  Player(int TURN) {
        this.TURN = TURN;
       }

    public void run(){

        int win = 0;
        int lose = 0;
        int draw = 0;
        boolean k = true;
        int j = 0; 
    for (j=0;j<=TURN;j++){
             String [] arr = {"ROCK", "PAPER", "SCISSORS"};
             Random Pick = new Random();

             // randomly selects an index from the arr
             int select = Pick.nextInt(arr.length); 

             // prints out the value at the randomly selected index
             System.out.println("Random String selected: " + arr[select]); 
        }
    }   
}
public class MainApp {

    public static void main(String[] args) {
        int TURN = 0;
        int No_Players = 0;
        int i=0;
        boolean h= true;
        int j=0;
        boolean k = true;


        System.out.println("Welcome to Rock-paper-scissors, this is a tutorial of threads");  
        Scanner number = new Scanner( System.in );
        System.out.println("Insert the number of players that will play");

        while (h){
            while (!number.hasNextInt()){
            System.out.println("You didnt insert a number please try again");
            number.next();
            }
            if(number.hasNextInt()){
             j = number.nextInt();
                if(j>1){
                    No_Players = j;
                    h=false;    
                }
                else {  
                    System.out.println("You need a value bigger than 1");
                }
            }
        }   
        System.out.println("Please enter how many turns you want each player to play");

        while (k){
            while (!number.hasNextInt()){
            System.out.println("You didnt insert a number please try again");
            number.next();
            }
            if(number.hasNextInt()){
             i = number.nextInt();
                if(i>0){
                    TURN = i;
                    k=false;    
                }
                else {  
                    System.out.println("You need a value bigger than 0");
                }
            }
        }   
        System.out.println("This game will have " + No_Players +" players and each one will have " + TURN + " turns");

        Map<String,Thread> map = new HashMap<>();
        for (int l = 0; i < No_Players; ++i) {
           String name = "Player_" + i;
           Player player = new Player(TURN);

           player.setName(name);
           map.put(name, player);
           player.start();
        }

    }   
}

**Posted the whole code because of some misunderstandings.

KevinO
  • 4,303
  • 4
  • 27
  • 36
  • I don't see any multithreading here at all. You've got a _loop_, but that's quite different, and this one will be executed on just a single thread. What are you trying to do? What's supposed to happen when you instantiate a Player at the end of the loop, and then never use it? – yshavit Mar 30 '16 at 21:31
  • 2
    The variable of type String as well as the variable of type Player is named `Name`. Change one of them – user Mar 30 '16 at 21:31
  • should i post the whole code or change the tags ... i am new here – Alex Metsis Mar 30 '16 at 21:32
  • 1
    OT: variable names should not start with an uppercase letter https://docs.oracle.com/javase/tutorial/java/nutsandbolts/variables.html – sinclair Mar 30 '16 at 21:33
  • After the most recent edit to fix the case of the variable names, there is _still_ a duplicate variable `name`, declared as `String name` and `Player name`. I would suggest the latter should be `Player player = new Player(TURN);`. – KevinO Mar 30 '16 at 21:56
  • of course there is still a duplicate variable, thats what the question is all about .) @KevinO – eckes Mar 31 '16 at 10:44
  • 1
    @eckes. My apologies. You are correct about the question and what should be there for the code to match. The case changing without the removal of the duplicate name caught me off guard. – KevinO Mar 31 '16 at 19:44
  • @KevinO yes - exepected - ... actually I added a comment to explain it, not sure where it is gone, so my bad. – eckes Mar 31 '16 at 19:53
  • You should implement Runnable, not extend Thread (http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread?rq=1) – Software Engineer Mar 31 '16 at 20:21

1 Answers1

0

Assuming that Player implements Runnable.

Map<String,Thread> map = new HashMap<>();
for (int i = 0; i < numPlayers; ++i) {
   String name = "Player_" + i;
   Player player = new Player(TURN);
   Thread t = new Thread(player):
   t.setName(name);
   map.put(name, t);
   t.start();
}

You can then retrieve the thread by the player name. You can also add a thread group if desired.

Based upon a comment that Player extends Thread (edit: fixed the Map definition to use Player rather than Thread).

Map<String,Player> map = new HashMap<>();
for (int i = 0; i < numPlayers; ++i) {
   String name = "Player_" + i;
   Player player = new Player(TURN);

   player.setName(name);
   map.put(name, player);
   // thread may need to be started elsewhere depending upon the requirement
   player.start();
}

Elsewhere to get the particular Player, just do:

Player p = map.get(playerName);

Based upon a comment, here is working example that show Player, extending Thread, using the Map suggested above, and displaying the players using the .getName() method on a Player object.

public class TestPlayer
{

public TestPlayer()
{
}


public static void main(String[] args)
{
    int numPlayers = 5;

    Map<String,Player> map = new HashMap<>();
    for (int i = 0; i < numPlayers; ++i) {
       String name = "Player_" + i;
       Player player = new Player(0);

       player.setName(name);
       map.put(name, player);
       // thread may need to be started elsewhere depending upon the requirement
       player.start();
    }

    for (Player p : map.values()) {
        System.out.println("Found player : " + p.getName());
    }


}


static class Player extends Thread
{
    private int turn;

    public Player(int turn)
    {
        this.turn = turn;
    }

    @Override
    public void run()
    {
        System.out.println("Running player " + 
                Thread.currentThread().getName() +
                " turn " + this.turn);
    }
}

}

Output: Running player Player_1 turn 0 Running player Player_3 turn 0 Running player Player_0 turn 0 Running player Player_2 turn 0 Running player Player_4 turn 0 Found player : Player_3 Found player : Player_2 Found player : Player_4 Found player : Player_1 Found player : Player_0

KevinO
  • 4,303
  • 4
  • 27
  • 36
  • it extends thread but thanks anyway i think mapping will help too – Alex Metsis Mar 30 '16 at 21:36
  • @AlexMetsis, if Player extends thread, then you just need to place the Player object in the Map, and not create a new thread based on it. – KevinO Mar 30 '16 at 21:38
  • @AlexMetsis, for the map.put(), yes. I made an edit assuming Player extends Thread (though I forgot to update the Map definition, will fix). – KevinO Mar 30 '16 at 21:47
  • You can also implement a constructor for `Player` which sets the player and thread name `Map map = new HashMap<>(); for (int i = 0; i < numPlayers; ++i) { String name = "Player_" + i; Player player = new Player(name, TURN); map.put(name, player); }` – eckes Mar 30 '16 at 21:57
  • what about when i want the name of the thread to be printed out, what command should i put ? – Alex Metsis Mar 30 '16 at 21:59
  • @eckes, indeed a good point. It is frequently unclear to me how deep into various suggestions to descend. As you noted, setting the name on the Player object would be a good idea, and then I would override the `.equals()` and `.hashCode()` methods of Player, and retrieve via the equality check. I would also not extend Thread but Runnable, and probably use the Executor system. – KevinO Mar 30 '16 at 22:00
  • @AlexMetsis, because Player extends thread, we set the name of the Thread object, so one can use `player.getName()`, which returns the name of the thread. One nice "feature" here is that in a debugger, the threads will be named the name of the player, making it a bit easier to traverse. – KevinO Mar 30 '16 at 22:01
  • I used the getName() and when i wanted to print it, it wouldn't appear anything. – Alex Metsis Mar 31 '16 at 19:27
  • @AlexMetsis, the getName() (unless overridden) from the Thread class (which is what Player extends) should give you the text you set in the setName on the player object. Every thread has a name, so I'm not sure how you would get nothing. Can you edit your question with the updated code? – KevinO Mar 31 '16 at 19:41
  • Just to echo the concerns, extending Thread in a business/domain object is very ugly. `getName()` is a good example for the conflict to expect. Besides it totally does not fit in any `Executor`-like framework – eckes Mar 31 '16 at 19:55
  • i will post all the code but is not like proper finished – Alex Metsis Mar 31 '16 at 20:02
  • i hope now you can get a better idea – Alex Metsis Mar 31 '16 at 20:05
  • @AlexMetsis, I looked at the posted code, but I do not see where you called the player.getName(). In all likelihood, I made a mistake by suggesting the question be edited rather than starting a new question. This question needs the original problem put back, and the code where you attempted to print the name needs to be provided. Again, I think separate question. The particulars of the duplicate name problem I think are resolved, and you should probably accept an answer and open a new question. – KevinO Mar 31 '16 at 20:13
  • oh that i just deleted it because it wasnt working so i didnt put it in. String P= player.getName(); System.out.println("Name :" + P); i putted this after the player.start(); – Alex Metsis Mar 31 '16 at 20:15