避免在实用程序中等待/通知挂起/恢复线程 [英] Avoiding wait/notify in a utility to suspend/resume threads

查看:49
本文介绍了避免在实用程序中等待/通知挂起/恢复线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现以下 Java 接口以允许暂停和恢复线程.我有一个使用 wait()/notifyAll() 的工作版本,但我想知道是否有更简单的方法来做到这一点(比如,在 java.util.concurrent 中使用一些漂亮的小部件)?

I'm implementing the following Java interface to allow threads to be paused and resumed. I've a working version that uses wait()/notifyAll(), but I wondered if there was an easier way to do it (say, using some nifty widget in java.util.concurrent)?

public interface Suspender {

    /**
     * Go into pause mode: any threads which subsequently call maybePause()
     * will block. Calling pause() if already in pause mode has no effect.
     */
    void pause();

    /**
     * Leave pause mode: any threads which call maybePause() will not block,
     * and any currently paused threads will be unblocked. Calling resume()
     * if not in pause mode has no effect.
     */
    void resume();

    /**
     * If the Suspender is in pause mode, block, and only resume execution
     * when the Suspender is resumed. Otherwise, do nothing.
     */
    void maybePause();

}

推荐答案

可以轻松地在 java.uitl.concurrent.Semaphore 持有 1 个许可证.

An implemetation of this can easily be built on top of a java.uitl.concurrent.Semaphore holding 1 permit.

  • pause() 获取许可(阻塞直到获得许可)
  • resume() 再次释放许可.
  • maybePause() 获取许可并阻止直到它得到它.然后再次释放它.
  • pause() takes the permit (blocking until it gets it)
  • resume() releases the permit again.
  • maybePause() takes the permit and blocks until it gets it. Then releases it again.

要在同一个 Suspender 上处理多个暂停请求,您可以使用另一个信号量作为更改暂停状态的权限,并在 pause 和 resume 方法中使用它.

To handle multiple pause requests on the same Suspender, you could use another semaphore that acts as a permission to change the pause state, and use that in both the pause and resume methods.

编辑

好吧,一旦我开始写作,我意识到这并不像我想象的那么简单.尽管如此,我还是设法使用(甚至只有一个)信号量编写了一个实现:

Ok, once I got to writing I realized it wasn't as simple as I imagined. Nevertheless I did manage to write an implementation using (even just one) Semaphore :

@ThreadSafe
public class SuspenderImpl implements Suspender {

    @GuardedBy("stateLock")
    private boolean paused;
    @GuardedBy("stateLock")
    private int pausedThreads;
    private final Semaphore token = new Semaphore(0);
    private final Object stateLock = new Object();

    @Override
    public void pause() {
        synchronized (stateLock) {
            paused = true;
        }
    }

    @Override
    public void resume() {
        synchronized (stateLock) {
            paused = false;
            token.release(pausedThreads);
            pausedThreads = 0;
        }
    }

    @Override
    public void maybePause() {
        synchronized (stateLock) {
            if (paused) {
                pausedThreads++;
            } else {
                token.release();
            }
        }
        try {
            token.acquire();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

基本思想与我原来的有很大不同.在此实现中,maybePause() 方法根据暂停的布尔标志决定是否立即释放许可.如果设置,许可将添加到信号量并立即获得.如果不设置,暂停线程的数量会增加,信号量上的获取将阻塞.

The basic idea differs significantly from my original. In this implementation the maybePause() method decides whether to immediately release a permit or not, based on a paused boolean flag. If set, a permit is added to the Semaphore and the immediately acquired. If not set the number of paused threads is increased and the acquire on the semaphore will block.

pause() 方法只是设置标志.resume() 方法将标志设置为 false,释放等于暂停线程数的许可并将该计数设置为零.

The pause() method simply sets the flag. The resume() method sets the flag to false, releases permits equal to the number of paused threads and sets that count to zero.

所有可变状态都由内部锁保护.

All mutable state is guarded by an internal lock.

这篇关于避免在实用程序中等待/通知挂起/恢复线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆