我正在使用Gosling的书来学习Java。在专门讨论多线程编程的章节中有一个问题: 编写一个程序,它将在会话开始时每秒创建一条消息。该程序的另一个线程应该每15秒创建一条消息。您应该提供计算时间的线程每次第二次通知的可能性。 这是我的解决方案(它不起作用,我无法理解为什么,我认为,我只是无法正确理解创建线程的原则):
public class test {
public static void main (String [] args) throws InterruptedException{
chrono my=new chrono();
my.timer();
Runnable t1=new messenger(5);
Runnable t2=new messenger(1);
new Thread(t1, "t1").start();
new Thread(t2, "t2").start();
}
}
class chrono {
static int time=0;
public synchronized void timer() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
notifyAll();
}
}
class messenger implements Runnable {
int time;
messenger(int time) {
this.time=time;
}
synchronized void timerListener() {
try {
while (chrono.time%time!=0) {
wait();
}
System.out.println("Thread "+this.time);
} catch(InterruptedException e) {}
}
public void run() {
timerListener();
}
}
新版本:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<6;i++) {
synchronized(my) {
my.timeCount();
my.notifyAll();
}
}
}
}
class Chronometr {
static int time=0;
public void timeCount() throws InterruptedException {
Thread.sleep(1000);
time++;
System.out.println(time);
}
}
class Messenger implements Runnable{
int time;
public Chronometr ch;
Messenger(int time, Chronometr ch) {
this.time=time;
this.ch=ch;
}
public void waitForTime() {
synchronized (ch) {
try{
while (Chronometr.time%time!=0)
ch.wait();
System.out.println("Thread "+this.time);
}
catch(InterruptedException e) {}
}
}
public void run() {
waitForTime();
}
}
Last change:
public class test {
public static void main (String [] args) throws InterruptedException{
Chronometr my=new Chronometr();
Runnable t1=new Messenger(5, my);
new Thread(t1, "t1").start();
for (int i=0;i<10;i++) {
synchronized(my) {
Chronometr.time+=1;
System.out.println(Chronometr.time);
my.notifyAll();
//my.wait();
}
Thread.sleep(1000);
}
}
}
答案 0 :(得分:1)
编辑:刚刚注意到另一个大问题:代码在synchronized
块内调用Thread.sleep()。没有!没有!没有!没有!不!
当我按原样运行你的程序的新版本时,Messenger线程通常永远不会运行:这就是我的想法:
main thread messenger thread
----------- ----------------
starts messenger
locks chronometer
sleeps enters waitForTime()
blocks trying to lock
chronometer
---one second later---
wakes up from sleep
increments time
prints message
calls notifyAll()
(Has no effect, 'cause
messenger is not in
wait() call)
ulocks the lock
re-locks the lock wakes up
sleeps blocks trying to lock
chronometer
. .
. .
. .
尝试将Thread.sleep(1000)调用从Chronometer.timeCount()方法移出到synchronized(my)
块的main()方法 outside 之外。我猜测输出会更符合您的预期。
原帖在线下,
你最大的问题是:
chrono.timer()方法调用notifyAll()本身(即,在&#34; my&#34;变量在main()中引用的chrono实例)。谁在那个对象上调用wait()?没有人是谁。你的消息对象会自己等待()。谁通知他们?没有人是谁。
其他评论(无特定顺序):
(1)类名应为CamelCase,以大写字母开头。您的代码看起来越像其他人,其他人就越愿意尝试理解并帮助您。
(2)如果您只有一个FooBarBaz类型的变量,那么该变量应该命名为fooBarBaz。同样的原因。
(3)类名应该是名词(例如,Chronometer而不是模糊的计时器),方法名应该是动词(例如,waitForTimerTick()而不是timerListener())。同样的原因。
(4)my.timer()
;在main中调用不会对您创建的线程产生任何可能的影响,并在返回后启动。如果调用notify()时foo.notify()
中没有其他线程已经等待,则foo.wait()
调用 nothing 。
(4a)一个名为&#34; my&#34;的变量。是一种憎恶。
(5)my.timer()
呼叫等待一秒钟,增加my.time,通知任何人,然后完成。好的。特别是,没有人会再次增加我的时间。
(5a)问题陈述清楚地表明该程序应该永远定期打印出消息,但程序中除了wait()
循环之外,没有循环。 timerListener()。
(6)在尝试处理线程之前,您可能希望获得编写解决实际问题的单线程程序的更多经验。