簡體   English   中英

兩個線程完成執行后清理

[英]Cleaning up after two threads finish execution

我有一個運行作業的應用程序,每個作業需要兩個線程。 這兩個線程通常會做一些工作並且很快就會完成。 然后在第二個線程完成之后我需要做一些清理,但由於線程正在做一些網絡IO,因此一個線程可能會被阻塞很長時間。 在這種情況下,我希望在第一個線程完成后幾秒鍾進行清理。

我在回調類中使用以下代碼實現了此行為:

private boolean first = true;

public synchronized void done() throws InterruptedException {
    if (first) {
        first = false;
        wait(3000);
        // cleanup here, as soon as possible
    }
    else {
        notify();
    }
}

兩個線程在完成時都會調用done()方法。 然后第一個將在wait()中阻塞最多3秒,但是當秒線程調用done()方法時將立即通知。

我已經測試了這個實現,它似乎運行良好,但我很好奇是否有更好的方法來做到這一點。 雖然這個實現看起來並不太復雜,但我擔心我的程序會死鎖或者有一些意想不到的同步問題。

由於done方法是同步的,因此一次只能執行一個線程,第二個線程將等待發送notify直到第一次完成整個作業,這可能會導致性能瓶頸。

我寧願用短的同步塊來設計它,這將首先主要更新boolean first

我希望我明白你的需要。 你想等待thread-a完成然后等待3秒或者等待thread-b的結束。

最好使用較新的Concurrent工具而不是舊的wait/notify因為它們有很多邊緣情況。

// Two threads running so count down from 2.
CountDownLatch wait = new CountDownLatch(2);

class TestRun implements Runnable {

    private final long waitTime;

    public TestRun(long waitTime) {
        this.waitTime = waitTime;
    }

    @Override
    public void run() {
        try {
            // Wait a few seconds.
            Thread.sleep(waitTime);
            // Finished! Count me down.
            wait.countDown();
            System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
        } catch (InterruptedException ex) {
            System.out.println(Thread.currentThread().getName() + " - Interrupted");
        }
    }

}

public void test() throws InterruptedException {
    // ThreadA
    Thread threadA = new Thread(new TestRun(10000), "Thread A");
    // ThreadB
    Thread threadB = new Thread(new TestRun(30000), "Thread B");
    // Fire them up.
    threadA.start();
    threadB.start();
    // Wait for all to finish but threadA must finish.
    threadA.join();
    // Wait up to 3 seconds for B.
    wait.await(3, TimeUnit.SECONDS);
    System.out.println(new Date() + ": Done");
    threadB.join();
}

愉快地打印:

Tue Sep 15 16:59:37 BST 2015: Thread A - Finished
Tue Sep 15 16:59:40 BST 2015: Done
Tue Sep 15 16:59:57 BST 2015: Thread B - Finished

添加

隨着新的清晰度 - 任何線程的結束啟動計時器 - 我們可以使用第三個線程進行清理。 每個線程在完成時都必須調用一個方法來觸發清理機制。

// Two threads running so count down from 2.
CountDownLatch wait = new CountDownLatch(2);

class TestRun implements Runnable {

    private final long waitTime;

    public TestRun(long waitTime) {
        this.waitTime = waitTime;
    }

    @Override
    public void run() {
        try {
            // Wait a few seconds.
            Thread.sleep(waitTime);
            // Finished! Count me down.
            wait.countDown();
            System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
            // Record that I've finished.
            finished();
        } catch (InterruptedException ex) {
            System.out.println(Thread.currentThread().getName() + " - Interrupted");
        }
    }

}

Runnable cleanup = new Runnable() {

    @Override
    public void run() {
        try {
            // Wait up to 3 seconds for both threads to clear.
            wait.await(3, TimeUnit.SECONDS);
            // Do your cleanup stuff here.
            // ...
            System.out.println(new Date() + ": " + Thread.currentThread().getName() + " - Finished");
        } catch (InterruptedException ex) {
            System.out.println(Thread.currentThread().getName() + " - Interrupted");
        }
    }

};

final AtomicBoolean cleanupStarted = new AtomicBoolean(false);

private void finished() {
    // Make sure I only start the cleanup once.
    if (cleanupStarted.compareAndSet(false, true)) {
        new Thread(cleanup, "Cleanup").start();
    }
}

public void test() throws InterruptedException {
    // ThreadA
    Thread threadA = new Thread(new TestRun(10000), "Thread A");
    // ThreadB
    Thread threadB = new Thread(new TestRun(30000), "Thread B");
    // Fire them up.
    threadA.start();
    threadB.start();
    System.out.println(new Date() + ": Done");
}

暫無
暫無

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

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