我正在尝试编写一个使用多个线程来创建计时器的简短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秒的消息。如何将这三个线程一起运行以组合一个工作计时器?
答案 0 :(得分:3)
在您的代码中,您使用类T2和T3来打印7秒和15秒的消息,但是没有标识哪个是哪个,它们实际上是相同的,保存名称和打印的字符串。当调用notify()时,没有给出锁定的可指定顺序。来自Javadocs的notify():
唤醒的线程将以通常的方式与可能主动竞争同步此对象的任何其他线程竞争
无论哪种方法(T3的run()或T3的run()获得锁定getSharedTime()都将继续并打印。请查看this question和Javadocs以获取更多相关信息。
这是做同样事情的类似方法,我移动了检查,如果时间是7或15的倍数到他们各自的类,并构造了wait()&s;并且notify()&# 39;不同。我还将打印与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();
}
}