簡體   English   中英

調度線程和同步方法

[英]Scheduling Threads and Synchronized Methods

我創建了一個稱為TSchedule的類,該類實現Runnable並擴展Thread,並將用於對少數幾個線程(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

問題在於,應在不同的對象上進行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 ,您將看到需要在同一鎖定對象上進行調用以得到您期望的行為。

解決問題的一種方法是用synchronized塊包圍if塊,然后更改wait()調用:

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

因此,每個TSchedule等待其依賴關系完成,然后通知自己。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM