【问题标题】:thread-safe stopwatch API线程安全的秒表 API
【发布时间】:2012-06-25 00:24:02
【问题描述】:

我想知道如何编写线程安全的秒表。下面是一个简单的秒表实现,它提供了秒表的基本操作,但它不是线程安全的。

现在,我能想到的就是为每个方法(start()、lap()、stop()、reset())添加同步。是否有其他方法可以在秒表上实现线程安全?

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

public class Stopwatch {
    private long startTime;
    private long endTime;
    private boolean isRunning;

    // lapTimes is able to record all the lap time.
    private CopyOnWriteArrayList<Long> lapTimes;

    Stopwatch() {
        isRunning = false;
        lapTimes = new CopyOnWriteArrayList<Long>();
    }

    public void start() {
        if (!isRunning) {
            isRunning = true;
            startTime = System.currentTimeMillis();
        } else {
            throw new IllegalStateException("cannot start when running!");
        }
    }

    public void lap() {
        if (isRunning) {
            endTime = System.currentTimeMillis();
            lapTimes.add(endTime - startTime);
            startTime = endTime;
        } else {
            throw new IllegalStateException("cannot lap when not running!!");
        }
    }

    public void stop() {
        if (isRunning) {
            endTime = System.currentTimeMillis();
            lapTimes.add(endTime - startTime);
            isRunning = false;
        } else {
            throw new IllegalStateException("cannot stop when not running!");
        }
    }

    public void reset() {
        isRunning = false;
        lapTimes.clear();
    }

    public List<Long> getLapTime() {
        return lapTimes;
    }

}

我想做的是让多个线程共享一个秒表对象。

假设我们有两个线程:线程 A 和线程 B。线程 A 启动秒表,并且晚了几秒钟,它调用了停止。当它刚刚结束 if 语句(stop 方法的第一行)时,线程 B 被调用,它也调用了 stop 方法。后来线程A继续执行stop方法,没有任何异常。

这不是我想要的,因为线程安全秒表无法停止两次,我只想知道如何摆脱它。

【问题讨论】:

  • 鉴于这些方法中的大多数都需要访问对象的大部分字段,您不妨将它们同步。如果各种方法需要访问不同的“资源”,您可以获得性能优势,并且实现更细粒度的锁是可行的,但这里不是这种情况。
  • 我认为尝试使此类线程安全是不明智的。例如,如果一个线程调用start,一个线程调用stop,会发生什么?如果你让它成为线程安全的,那么结果将基本上是随机的,这无论如何都不会有用。无论调用到这个代码中的什么代码都必须同步自身,否则无论这个类做什么,它都会得到无意义的结果——那么为什么要为实际上不能解决问题的同步支付开销呢?

标签: java thread-safety stopwatch


【解决方案1】:

您是否希望它是线程安全的,因为... (a) 多个线程可能正在启动秒表并执行圈数,或者 (b) 一个线程可能会启动秒表,而另一个线程可能会使用同一个秒表完成一圈?

【讨论】:

  • 我想我想实现第二个,而第一个似乎每个线程都有自己的秒表,因此不会共享一个对象。
猜你喜欢
  • 2015-12-21
  • 2013-05-04
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多