如何设计将由多个线程访问的类。

时间:2016-05-19 09:55:15

标签: java multithreading

我想创建一个类,它将被多个线程访问以获取数据。所以我有一个像这样的方法:

public static String getData(){
 //some logic before returning the value
 // return data once initialized
}

现在将有方法设置该数据:

private void setData(){
}

我希望此setData只能被调用一次,因此请考虑将其包含在static块中:

static {
  setData()
}

现在我有这些问题:

  1. 我打算为此创建一个静态类,以便其他线程可以像这样调用:

    ThreadSafe.getData();

  2. 在我的getData中,我想在返回之前首先检查该数据的有效性,如果数据无效,我需要再次调用setData然后将其返回。鉴于这一事实,我需要getData synchronized对吗?

  3. 我的上述方法是否适用于多线程环境?

3 个答案:

答案 0 :(得分:1)

你可以通过多种方式实现它。

  1. 您可以使用volatile变量(如果一个Thread write/modify数据和所有other Threads读取数据
  2. 您可以使用AtomicReference个变量(如果多个线程可以读取/修改共享数据
  3. 如果你在这些变量之上有一些原子事务而不仅仅是写&阅读数据时,您必须使用synchronized或其他替代方案(如Lock API)保护您的商业交易代码块。

    有关详细信息,请参阅此jenkov教程。

    带有代码示例的相关SE帖子:

    Difference between volatile and synchronized in Java

    Avoid synchronized(this) in Java?

    When to use AtomicReference in Java?

    What is the difference between atomic / volatile / synchronized?

答案 1 :(得分:1)

您可以使用同步:

public class ThreadSafe {

    private static final Object monitor = new Object();
    private static final String data;

    static {
        setData();
    }

    private static void setData() {         
            data = String.valueOf(System.currentTimeMillis());
    }

    public static String getData() {
        synchronized(monitor) {
            if (data.indexOf("7") < 0) { 
                // recalculate invalid data
                setData();
            }
            return data;
        }
    }
}

答案 2 :(得分:0)

我想说你最好同步(用双锁检查)块来调用getData()中的setData()。假设这是一种罕见的情况,这应该在高负载下更快地工作。