2015-12-24 3 views
3

Я новичок в программировании с многопоточным, поэтому я не совсем понимаю, почему мой код работает неправильно.Остановка потока, когда другой поток завершен в java

Я искал и искал на этом сайте ответы и на google тоже, но ничего не нашел (или я не знал, что это правильный ответ для меня), поэтому я спрашиваю вас у экспертов.

Я должен сделать ввод пользователем числа. Это число будет количеством органов в Фибоначчи, которое будет отображаться на экране, с задержкой в ​​1 секунду между ними. Другой поток отобразит на экране время, прошедшее до сих пор, каждые 5 секунд.

Я использовал цикл, но это не имеет смысла, потому что мне нужно, чтобы он продолжался, пока первый поток работает и останавливается, когда его нет.

Я не знаю, как остановить второй поток, когда первый, который создает фибоначчи, остановился.

Я пытался использовать join(), notifyAll(), stop(), но я явно чего-то пропустил. Я дам код (без join, notifyAll, или stop, потому что он не работает для меня).

Это главное:

import java.util.Scanner; 
    public class MainFibonacci 
    { 

    public static void main(String[] args) throws InterruptedException { 

     int num; 
     System.out.println("How many numbers in Fibonacci would you like?"); 
     Scanner in = new Scanner(System.in); 
     num=in.nextInt(); 
     FibTime f1=new FibTime(); 
     MakeFibonacci m1= new MakeFibonacci(num); 
     m1.start(); 
     f1.start(); 
    } 
} 

Класс, который создает Фибоначчи:

public class MakeFibonacci extends Thread{ 
private int number; 

//constructor 
public MakeFibonacci(int num){ 
    this.number=num; 
} 

public void run() 
{ 
    for (int i=1;i<=number;i++) 
    { 
     System.out.print(fibonacci(i) +" "); 

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

    //The actual method that creates the fibonacci 
    public int fibonacci(int number) 
    { 
     if(number == 1 || number == 2) 
     { 
      return 1; 
     } 

     int num1=1, num2=1, next=1; 

     for(int i = 3; i<= number; i++) 
     { 
      next = num1 + num2; 
      num1 = num2; 
      num2 = next; 

     } 
     return next; 
    } 

} 

Второй класс с mwthos за сколько времени прошло:

public class FibTime extends Thread 
{ 
    private int timePassed=5; 

    public void run() 
    { 
     for(int i=1;i<timePassed;i++) 
     { 
     try 
     { 
      Thread.sleep(5000); 
    System.out.println("Time so far is "+ (timePassed*i) +" seconds");    
     } 
     catch (InterruptedException e) 
     { 

      e.printStackTrace(); 
     } 

     } 

    } 

} 
+0

В дизайне определенно запах. – Taky

+0

Что это значит? @Taky –

+0

Я вижу два варианта. (1) Есть некоторая общая volatile boolean переменная с начальным значением как true, которое используется обоими нитями. Второй поток ('FibTime') циклически, пока эта переменная не будет истинна, а не current for loop, и первый поток (' MakeFibonacci') помечает эту переменную как ложную, когда она выходит из цикла for. (2) Другой вариант - использовать один поток вместо двух. Первый поток ('MakeFibonacci') будет заботиться о том, чтобы печатать число фибоначчи каждую секунду и сообщение« время до сих пор .. »всякий раз, когда i% 5 == 0. –

ответ

1

Вы создали объект для FibTime в самой главной функции. Вместо этого вы можете объявить его как члена MakeFibonacci, создайте объект для FibTime в конструкторе класса MakeFibonacci и запустите его там сам. Теперь у вас будет ссылка на объект FibTime. Вы можете остановить поток FibTime с помощью этой ссылки. Поместите команду .stop() после цикла for, который печатает номера Фибоначчи.

Другой способ - передать объект потока FibTime, который выполняется как аргумент конструктора MakeFibonacci и назначить его члену MakeFibonacci. . Остановка этого нить таким же образом ..

+0

Здравствуйте, спасибо за помощь. У меня есть вопрос, пожалуйста. я пытаюсь понять, что вы здесь сказали, но я не могу понять вас хорошо. Я немного смущен, как вы можете видеть. можете ли вы отредактировать свой ответ и привести пример того, что вы сказали? Благодарю. –

+0

Не создавайте объект для FibTime в основном классе. Объявите объект FibTime как член класса MakeFibonacci и запустите его в конструкторе MakeFibonacci. Как только цикл for, который печатает значение no, полностью остановит поток FibTime методом stop(). Например: f1.stop() –

0

Одна вещь, которую вы могли бы сделать:

public class Beginning { 

private static volatile boolean itIsRunning = true; 
final static CountDownLatch startGate = new CountDownLatch(1); 

public static void main(String[] args) { 

    Thread fibonnaciThread = new Thread(new Fibonnaci(10)); 
    Thread timerThread = new Thread(new FibTimer()); 

    fibonnaciThread.start(); 
    timerThread.start(); 

    startGate.countDown(); 
    while (itIsRunning) 
     ; 

    timerThread.interrupt(); 

    System.out.println("Interuppted timer"); 
} 

private static class Fibonnaci implements Runnable { 

    private int target; 

    public Fibonnaci(int target) { 
     this.target = target; 
    } 

    @Override 
    public void run() { 
     try { 
      startGate.await(); 

      for (int i = 1; i <= target; i++) { 
       System.out.print(fibonacci(i) + " "); 

       Thread.sleep(1000); 

      } 

      itIsRunning = false; 
     } catch (InterruptedException e) { 

      Thread.currentThread().interrupt(); 
     } 

    } 

    // The actual method that creates the fibonacci 
    private int fibonacci(int number) { 
     if (number == 1 || number == 2) { 
      return 1; 
     } 

     int num1 = 1, num2 = 1, next = 1; 

     for (int i = 3; i <= number; i++) { 
      next = num1 + num2; 
      num1 = num2; 
      num2 = next; 

     } 
     return next; 
    } 

} 

private static class FibTimer extends Thread { 

    public void run() { 
     try { 
      startGate.await(); 
      while (!Thread.currentThread().isInterrupted()) { 
       Thread.sleep(5000); 
       System.out.println("Time so far is " + System.nanoTime() + " seconds"); 
      } 
     } catch (InterruptedException e) { 

      Thread.currentThread().interrupt(); 
     } 

    } 
} 
} 

Это работает, как вы хотели. CountDownLatch должен убедиться, что оба потока начнутся в одно и то же время. Однако есть несколько моментов, которые вам нужны.

  1. Использование Thread.sleep() не лучшее решение. Вы можете использовать shceduledExecutors
  2. Это не лучший способ узнать, сколько Фибоначчи занимает определенное количество, но я дал его таким образом, чтобы продемонстрировать, как вы могли бы общаться между двумя разными потоками.

Примечание volatile. Если он нестабилен, он не будет работать правильно. (без синхронизации, по крайней мере).