Java 调度线程和同步方法

Java 调度线程和同步方法,java,multithreading,Java,Multithreading,我已经创建了一个名为TSchedule的类,它实现了Runnable并扩展了Thread,将用于对少数线程t1、t2、…、t8排序 TSSchedule的每个实例都以线程名称、到达时间睡眠时间、依赖项列表、TSSchedule数组和标志的形式传递 在每个线程执行完run方法之后,各自的线程都应该打印出thread.getName正在终止,但是,我似乎无法让所有线程都打印出来 public class TSchedule extends Thread implements Runnable {

我已经创建了一个名为TSchedule的类,它实现了Runnable并扩展了Thread,将用于对少数线程t1、t2、…、t8排序

TSSchedule的每个实例都以线程名称、到达时间睡眠时间、依赖项列表、TSSchedule数组和标志的形式传递

在每个线程执行完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();
    }
 }
问题是wait和notify调用应该在不同的对象上进行

让我们使用t4进行一次试运行,t4取决于t1和t2,并且不终止

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运行,因为它没有任何依赖项,所以它将直接去通知。问题是它实际上调用了this.notify,而this.notify又是t1.notify,它应该调用t4.notify。t2也是这样

因此,没有人叫醒t4,它就呆在那里,等待有人告诉他继续

检查文档中的wait和notify:您将看到需要对同一个lock对象进行调用,以获得预期的行为

解决问题的一种方法是用同步块包围if块并更改等待呼叫:


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

wait做什么?wait会将当前线程置于等待状态,释放它在TSchedule对象上的锁,这允许其他线程实例输入checkDependencies。为什么要在同一类中实现runnable和extend Thread!因此,我可以通过调用Supername为每个线程实例命名,正如@MingtaoZhang所说,如果类扩展了线程,它就不需要再次实现Runnable。那么我怎么才能通知呢?请解释为什么每个依赖项都调用wait和notify?谢谢。有了我的解决方案,家长们正在明确地等待他们的依赖关系。同时,每个没有依赖项的TSSchedule将正常结束并通知。此通知将由显式等待的父级接收,依此类推。通过试运行帮助您理解这个概念。我已经编辑了我的解决方案,将notify添加到末尾,以使其更清晰。
t4 arrived at time 1398211394620
t1 arrived at time 1398211394622
t1 is terminating
t2 arrived at time 1398211394624
t2 is terminating
synchronized (dependencies[i]) {
    if (dependencies[i].done != true) {
        ...
        dependencies[i].wait();
        ...
    }
}
done = true;
notify();