我有一堂课,用于执行货币兑换监控活动,并且具有暂停和恢复的功能。关于班级设计,我有以下问题。


has_started是否必须具有挥发性?
suspend是否必须具有挥发性?我从Exampledepot看过示例,该标志未标记为volatile。
当我在InterruptedException期间遇到wait时,我应该return,还是忽略该异常?


另外,关于多个synchronized块,我也收到NetBeans警告。这是有效的警告吗?

public synchronized void suspend() {
    synchronized(currencyExchangeRunnable) {
        suspend = true;
    }
}


我的第一级同步用于防止多个线程执行挂起/恢复/启动/停止。我的第二个同步块是与wait/notify配对

我对暂停/恢复/启动/停止的初步测试是,它们按预期工作。但是,我不确定后面是否还有其他陷阱?



import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author yccheok
 */
public class CurrencyExchangeMonitor {

    /**
     * Starts currency exchange monitoring activities. This method can be called
     * multiple times. start/stop/suspend/resume are being synchronized with
     * each others.
     */
    public synchronized void start() {
        if (has_started) {
            return;
        }
        executor.submit(currencyExchangeRunnable);
        has_started = true;
    }

    /**
     * Stop all currency exchange monitoring activities. Once it is stopped, it
     * cannot be started again. This method will only return once it is being
     * terminated completely. start/stop/suspend/resume are being synchronized
     * with each others.
     */
    public synchronized void stop() {
        executor.shutdownNow();
        try {
            executor.awaitTermination(100, TimeUnit.DAYS);
        } catch (InterruptedException ex) {
            log.error(null, ex);
        }
    }

    /**
     * Temporary suspend all ongoing monitoring activities. This method can be
     * called multiple times. start/stop/suspend/resume are being synchronized
     * with each others.
     */
    public synchronized void suspend() {
        synchronized(currencyExchangeRunnable) {
            suspend = true;
        }
    }

    /**
     * Resume all ongoing monitoring activities. This method can be called
     * multiple times. start/stop/suspend/resume are being synchronized with
     * each others.
     */
    public synchronized void resume() {
        synchronized(currencyExchangeRunnable) {
            suspend = false;
            currencyExchangeRunnable.notify();
        }
    }

    private class CurrencyExchangeRunnable implements Runnable {
        @Override
        public void run() {
            while (!executor.isShutdown()) {
                synchronized(this) {
                    while (suspend) {
                        try {
                            wait();
                        } catch (InterruptedException ex) {
                            log.error(null, ex);
                            // Usually triggered by executor.shutdownNow
                            return;
                        }
                    }
                }
            }
        }
    }

    private volatile boolean suspend = false;
    private volatile boolean has_started = false;
    private final CurrencyExchangeRunnable currencyExchangeRunnable = new CurrencyExchangeRunnable();
    private final ExecutorService executor = Executors.newSingleThreadExecutor();
    private static final Log log = LogFactory.getLog(CurrencyExchangeMonitor.class);
}

最佳答案

(1,2)由于两个变量仅在同步块中访问,因此它们不必是volatile。

(3)通常最好用InterruptedException做些事情。但是,如果您控制进程中的所有代码,并且您从未中断线程,则可以忽略该线程。

如果代码编写不当,嵌套的同步块可能导致死锁。您必须始终(所有代码路径)以相同顺序获取锁。

我同意juskt的“ Java并发实践”。这是一本很好的书。

关于java - 有关挂起和恢复正在运行的线程的技术细节,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4727230/

10-14 11:58