在Java中,当另一个线程完成时如何停止一个线程

3

我是多线程编程的新手,所以我不太明白为什么我的代码没有正常工作。

我在这个网站和谷歌上搜索了很久,但是没有找到答案(或者我不知道对我来说它是否是正确的答案),所以我向您这些专家求助。

我需要让用户输入一个数字。这个数字将是斐波那契数列中要在屏幕上显示的器官数量,每个数字之间有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; 
    } 

}

第二个类别是关于时间流逝的神话:
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();
        }

       }

    }

}

设计中肯定有气味。 - Taky
那是什么意思?@Taky - user5533608
我看到两个选项。(1) 使用一个初始值为true的共享的易变布尔变量,由两个线程共同使用。第二个线程(FibTime)循环直到这个变量为true,而不是当前的for循环,并且第一个线程(MakeFibonacci)在它的for循环结束后将这个变量标记为false。(2) 另一个选项是只使用一个线程。第一个线程(MakeFibonacci)将负责每隔一秒打印斐波那契数和在i%5==0时打印"已经过去的时间.."的消息。 - Madhusudana Reddy Sunnapu
这是关于如何协调执行两个线程,还是您只想计算斐波那契线程完成执行需要多长时间? - idipous
2个回答

2
在主函数中,您已经创建了FibTime对象。相反,您可以将其声明为MakeFibonacci类的成员,在MakeFibonacci类的构造函数中创建FibTime对象并启动它。 现在,您将拥有FibTime线程的对象引用。您可以使用该引用停止FibTime线程。在打印斐波那契数列的for循环之后放置.stop()命令即可。
另一种方法是通过将正在执行的FibTime线程对象作为参数传递给MakeFibonacci构造函数,并将其分配给MakeFibonacci的成员。停止此线程的方式相同。

你好,感谢您的帮助。我有一些问题想问。我正在尝试理解您在这里说的话,但是我不能很好地理解您的意思。正如您所看到的,我有点困惑。您能否编辑您的答案并给出您所说内容的示例?谢谢。 - user5533608
不要在主类中创建FibTime对象。在MakeFibonacci类中声明一个FibTime对象作为成员,并在MakeFibonacci的构造函数中启动它。 一旦打印数字的for循环完成,使用stop()方法停止FibTime线程。例如:f1.stop()。 - Senthil Vidhiyakar

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() 不是最好的解决方案。你可以使用 scheduledExecutors
  2. 这不是计算斐波那契数列特定数字所需时间的最佳方法,但我以这种方式给出它,以演示如何在两个不同的线程之间通信完成。

请注意 volatile。如果不是 volatile,它将无法正常工作(至少没有同步)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接