Java中多线程编程的问题

时间:2014-07-24 16:34:59

标签: java multithreading

我正在使用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);
            }


        }
    }

1 个答案:

答案 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)在尝试处理线程之前,您可能希望获得编写解决实际问题的单线程程序的更多经验。