我正在尝试编写一个使用多个线程来创建计时器的简短Java程序。当计时器达到7或15秒时,它将打印一条消息。

我需要创建一个共享计数器。时间打印线程从执行开始就每秒将计数器递增1并打印其值。消息打印线程每隔十五秒打印一次消息,另一个消息打印线程每隔七秒打印一次不同的消息。这两个线程需要完成而无需修改时间打印线程。

所有这些线程都需要共享每秒更新的计数器对象。时间打印线程将在每次更新时通知其他线程读取计数器对象。然后,每个消息打印线程将读取计数器值,并查看其分配的时间段是否已经发生。

输出应如下所示:

1 2 3 4 5 6
7 second message
7 8 9 10 11 12 13
7 second message
14
15 second message
15 16 17 18 19 20
7 second message
21 22 23 24  . . .

为此,我需要为计时器创建一个线程,为7秒消息创建一个线程和为15秒消息创建一个线程。我在下面建立了这个:
import java.lang.Class;
import java.lang.Object;

class T1 extends Thread {
    private Main2 s;
    private int t;
    T1 (Main2 s) { this.s = s; }
    public void run()
    {
        while(true) {
            try { Thread.sleep(1000); }
            catch (InterruptedException e) { e.printStackTrace(); }
            s.setSharedTime (++t);
            System.out.print(t + " ");
        }
    }
}

class T2 extends Thread {
    private Main2 s;
    T2 (Main2 s) { this.s = s; }
    public void run()
    {
        while(true) {
            int t = s.getSharedTime ();
            System.out.println();
            System.out.println ("7 second message");
        }
    }
}

class T3 extends Thread {
    private Main2 s;
    T3 (Main2 s) { this.s = s; }
    public void run()
    {
        while(true) {
            int t = s.getSharedTime ();
            System.out.println();
            System.out.println ("15 second message");
        }
    }
}

public class Main2 {
    private int time;
    private boolean share = true;

    public static void main(String[] args) {
        Main2 s = new Main2();
        new T1 (s).start();
        new T2 (s).start();
        new T3 (s).start();
    }

    synchronized void setSharedTime (int s) {
        while (!share) {
            try { wait (); }
            catch (InterruptedException e) {}
        }
        this.time = s;
        if(s % 7 == 0)
            share = false;
        if(s % 15 == 0)
            share = false;
        notify ();
    }

    synchronized int getSharedTime () {
        while (share) {
            try { wait (); }
            catch (InterruptedException e) { }
        }
        share = true;
        notify ();
        return time;
    }
}

我遇到的问题是我无法在正确的时间抛出7秒和15秒消息。如何将这三个线程一起运行以构成一个工作计时器?

最佳答案

在您的代码中,您使用类T2和T3来打印7秒和15秒消息,但是没有标识哪个消息和它们实际上是相同的,保存了名称和要打印的字符串。调用notify()时,没有给出锁定的可指定顺序。从Javadocs中的notify():

唤醒的线程将以通常的方式与可能正在主动竞争以在此对象上进行同步的任何其他线程竞争

因此,获得getSharedTime()锁定的方法(T2的run()或T3的run())将继续并打印。有关更多信息,请查看this questionJavadocs

这是执行相同操作的类似方法,我将检查时间是否为7或15的倍数移到了各自的类上,并以不同的方式构造了wait()和notify()。我还将打印与Timer类同步,以便同时(有效)通知所有wait()。在Timer类中处理每秒钟的打印时间,现在,它的设置方式将提供您指定的输出,但是将打印和调用setTime以及将时间初始化为0时,将输出更准确的输出到当前时间。

class Timer extends Thread{
    private int time = 1;
    private boolean setting = false;

    public void run(){
        while(true){
            try {
                sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.print(time + " ");
            setTime(time + 1);
            //Switching the order of these 2 ^^^ statements and initializing time to 0 will give an output that is more accurate to the time.
        }
    }
    public synchronized int getTime(){
        while(setting){
            try {
                wait(); //This will only be run on the off-chance that setTime is being run at the same time.
            } catch (InterruptedException e) {  }
        }

        return time;
    }
    public synchronized void setTime(int t){
        setting = true;
        this.time = t;
        setting = false;
        notifyAll();
    }
}

class Timer7 extends Thread{
    Timer timer;
    public Timer7(Timer t){
        this.timer = t;
    }

    public void run(){
        synchronized(timer){
            while(true){

                try {
                    timer.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if(timer.getTime() % 7 == 0){
                    System.out.print("\n7 Second Message\n");
                }

            }
        }
    }
}

class Timer15 extends Thread{
    Timer timer;
    public Timer15(Timer t){
        this.timer = t;
    }

    public void run(){
        synchronized(timer){
            while(true){

                try {
                    timer.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                if(timer.getTime() % 15 == 0){
                    System.out.print("\n15 Second Message\n");
                }

            }
        }
    }
}

public class Main2 {

    public static synchronized void main(String[] args) {

        Timer timer = new Timer();
        timer.start();

        Timer7 t7 = new Timer7(timer);
        t7.start();

        Timer15 t15 = new Timer15(timer);
        t15.start();

    }

}

07-24 09:44
查看更多