2015-04-27 4 views
4

Я изучаю многопоточность на Java, поэтому теперь я создаю классическое приложение для черепах и заяц.Два потока, заканчивающиеся одновременно и доступ к одному и тому же методу

Для тех, кто не знаком с этой проблемой, в принципе, есть два гонщик:

  • Заяц, который работает 100 метров в каждом цикле, но имеет 90% шанс отдыха вместо запуска
  • черепахи, которая работает 10 метров в каждой петле, но никогда не лежит

Победителем первой является 1000 метров.

Мой код будет выглядеть так:

Основной класс:

public class THRace { 

    static Thread hare  = new Thread(new ThreadRunner("Hare",  90, 100)); 
    static Thread tortoise = new Thread(new ThreadRunner("Tortoise", 0, 10)); 

    public static void main(String[] args) { 
     hare.start(); 
     tortoise.start(); 
    } 

    public static void finished(Thread winner){ 
     if (winner.getName().equals("Hare")) tortoise.interrupt(); 
     else if (winner.getName().equals("Tortoise")) hare.interrupt();  
    } 

} 

ThreadRunner класс:

import java.util.Random; 

public class ThreadRunner implements Runnable { 

    private String name; 
    private int rest, speed; 

    public String getRacerName() { 
     return name; 
    } 

    public ThreadRunner(String name, int rest, int speed) { 
     this.name = name; 
     this.rest = rest; 
     this.speed = speed; 
    } 

    @Override 
    public void run() { 

     int meters = 0; 
     Random rn = new Random(); 

     Thread ct = Thread.currentThread(); 
     ct.setName(name); 

     while(!ct.isInterrupted()){ 
      if(rn.nextInt(100) + 1 > rest){ 
       meters += speed; 
       System.out.println(this.name + ": " + meters);     
      } 

      try { 
       Thread.sleep(100); 
      }catch (InterruptedException ex){ 
       return; 
       //break; 
      } 

      if(meters >= 1000){ 
       System.out.println(this.name + ": I finished!"); 
       THRace.finished(ct); 
       return; 
      } 

     } 
    } 

} 

Когда поток достигает 1000 метров он называет закончил метод из основного класса, и он останавливает другую нить. Мой код работает очень хорошо, но проблема в том, что происходит, когда есть галстук (когда заяц и черепаха достигают 1000 метров при одном и том же галстуке) оба победителя объявляются победителями, и я не хочу, чтобы это произошло.

Например, вы можете установить бегунов иметь 0% остальное шанс и с той же скоростью, так что они оба будут достигать 1000 метров, в то же время:

static Thread hare  = new Thread(new ThreadRunner("Hare",  0, 10)); 
static Thread tortoise = new Thread(new ThreadRunner("Tortoise", 0, 10)); 

И выход будет:

(...) 
Tortoise: 950 
Hare: 950 
Hare: 960 
Tortoise: 960 
Tortoise: 970 
Hare: 970 
Tortoise: 980 
Hare: 980 
Tortoise: 990 
Hare: 990 
Tortoise: 1000 
Hare: 1000 
Hare: I finished! 
Tortoise: I finished! 

есть ли способ для меня, чтобы «запереть» закончил метод, так что только один поток объявлен победителем?

+0

Возможный дубликат [Проблемы с синхронизацией со статическим методом в java] (http://stackoverflow.com/questions/6435675/synchronization-concerns-with-a-static-method-in-java) – ericbn

ответ

7

Если вы используете синхронизируются идентификатора перед законченным методом, первый поток, чтобы назвать это заблокирует ее, пока она не будет закончена. Поскольку вы прерываете другой поток, это должно работать отлично для вас.

synchronized public static void finished(Thread winner){ 
    if(winner.isInterrupted()) { 
     // sorry, the other thread beat you here 
     return; 
    } 

    if (winner.getName().equals("Hare")) tortoise.interrupt(); 
    else if (winner.getName().equals("Tortoise")) hare.interrupt();  
} 

Как уже упоминалось в свой комментарий, если другой поток уже в очередь и ждут, чтобы получить в готовом метод, вам нужно будет добавить проверку, чтобы увидеть, если ваш прерывались, прежде чем объявить себя победителем.

+0

О, спасибо , Я попытался использовать ** синхронизированный **, но сначала это не сработало, поэтому я подумал, что делаю что-то неправильно и неправильно. Но с вашим ответом я попытался найти, что было моей ошибкой: мне просто нужно было добавить условие, прежде чем печатать победителя «if (! Ct.isInterrupted()) System.out.println (this.name +«: Я закончил! »);» в классе ThreadRunner. Не могли бы вы добавить это в свой ответ, чтобы он мог быть более заметным для других людей? –

Смежные вопросы