调度线程和同步方法

时间:2014-04-23 00:01:43

标签: java multithreading

我创建了一个名为TSchedule的类,它实现了Runnable并扩展了Thread,并将用于对一些Threads(t1,t2,...,t8)进行排序。

每个TSchedule实例都以线程名称,到达时间(休眠时间),依赖项列表(TSchedule数组)和标志传递。

在每个线程完成执行run()方法之后,相应的线程应该打印出“Thread.getName()正在终止”,但是,我似乎无法将所有线程打印出来。

public class TSchedule extends Thread implements Runnable {
       private TSchedule[] dependencies;
       private int sleepTime;
           private boolean done;

    public TSchedule (String name, int sleep, TSchedule[] dependencies, boolean done) {
        super(name); 
        sleepTime = sleep; 
        this.dependencies = dependencies;
        this.done = done;
    }

    public void run() {
        try {
            sleep(sleepTime); 
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        System.err.println(getName() + " arrived at time " + System.currentTimeMillis());
        checkDependencies(dependencies);
        System.err.println(getName() + " is terminating");
    }

    public synchronized void checkDependencies(TSchedule[] dependencies) {
        if(dependencies != null)
            for(int i = 0; i < dependencies.length; i++) {
                if(dependencies[i].done != true) {
                    System.out.println(getName() + " waiting on " + dependencies[i].getName() 
                            + " time " + System.currentTimeMillis());
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        done = true;
        notify();
    }

    public static void main(String[] args) {
        TSchedule t1, t2, t3, t4, t5, t6, t7, t8;

        t1 = new TSchedule("t1", 4, null, false);
        t2 = new TSchedule("t2", 6, null, false);
        t3 = new TSchedule("t3", 7, null, false);
        t4 = new TSchedule("t4", 2, new TSchedule[] {t1, t2}, false);
        t5 = new TSchedule("t5", 3, new TSchedule[] {t3}, false);
        t6 = new TSchedule("t6", 1, new TSchedule[] {t3, t4}, false);
        t7 = new TSchedule("t7", 8, new TSchedule[] {t4}, false);
        t8 = new TSchedule("t8", 5, new TSchedule[] {t6}, false);

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
        t7.start();
        t8.start();
    }
 }

以下是我收到的输出:

t4 arrived at time 1398211394620
t6 arrived at time 1398211394620
t5 arrived at time 1398211394621
t4 waiting on t1 time 1398211394620
t5 waiting on t3 time 1398211394621
t6 waiting on t3 time 1398211394621
t1 arrived at time 1398211394622
t1 is terminating
t8 arrived at time 1398211394624
t8 waiting on t6 time 1398211394624
t2 arrived at time 1398211394624
t2 is terminating
t3 arrived at time 1398211394625
t3 is terminating
t7 arrived at time 1398211394627
t7 waiting on t4 time 1398211394627

1 个答案:

答案 0 :(得分:0)

问题是waitnotify调用应该在不同的对象上进行。

让我们使用t4进行干预,这取决于t1t2,并且不会终止。

t4 arrived at time 1398211394620
t1 arrived at time 1398211394622
t1 is terminating
t2 arrived at time 1398211394624
t2 is terminating

由于t4首先运行,它会看到t1尚未完成,并会调用wait()这是一种调用this.wait()的简短方法,即t4.wait() }

现在t1运行,因为它没有任何依赖关系,它将直接转到notify()。问题是,实际上调用的this.notify()反而是t1.notify(),而应该调用t4.notify()。与t2相同。

因此,没有人醒来t4,它会停留在那里,等待有人告诉他继续。

查看waitnotifyhttp://docs.oracle.com/javase/7/docs/api/java/lang/Object.html的文档,您将看到需要在同一个锁定对象上进行调用才能获得您期望的行为。

解决问题的一种方法是用if阻止synchronized阻止,并更改wait()来电:

synchronized (dependencies[i]) {
    if (dependencies[i].done != true) {
        ...
        dependencies[i].wait();
        ...
    }
}
done = true;
notify();

因此,每个TSchedule等待其依赖关系完成,然后通知自己。