单身和多线程

时间:2013-07-04 15:54:20

标签: java multithreading singleton

请查看下面的课程并告诉我以下代码是否是线程安全的。我的问题是,一个类的static方法和该方法调用单例实例的方法。此外,static实例调用Runnable方法。所以我要求你们看看代码 - static方法,它在多线程环境中调用singleton的方法 - 是否安全?

如果你回答我的问题,我将非常感激。

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

public class SingletonCls {
    private static SingletonCls singletonInstance = null;

    private SingletonCls() {
    }

    public static SingletonCls getIntance() {
        if (SingletonCls.singletonInstance == null) {
            singletonInstance = new SingletonCls();
        }
        return SingletonCls.singletonInstance;
    }

    public List<Map<String, String>> call(String id) throws Exception {
        List<Map<String, String>> list = new ArrayList<Map<String, String>>();
        BufferedReader br = null;
        final String col = "col";
        try {
            br = new BufferedReader(new FileReader("test.txt"));
            String lineStr = null;
            while ((lineStr = br.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(lineStr, ",");
                int colIdx = 1;

                if (lineStr.startsWith(id)) {
                    Map<String, String> map = new HashMap<String, String>();
                    while (st.hasMoreTokens()) {
                        String value = st.nextToken();
                        map.put(col + (colIdx++), value);
                    }
                    list.add(map);
                }
            }

        } finally {
            if (br != null) {
                br.close();
            }
        }
        return list;
    }
}


import java.io.IOException;
import java.util.List;
import java.util.Map;

public class TestSingleTonCaller {

    public static List<Map<String, String>> getData(String id) throws Exception {
        List<Map<String, String>> list = SingletonCls.getIntance().call(id);
        return list;
    }
}



import java.io.IOException;
import java.util.List;
import java.util.Map;

public class RunnableSingleTonExe implements Runnable {
    private final String id;

    public RunnableSingleTonExe(String inId) {
        this.id = inId;
    }

    public void run() {
        try {
            List<Map<String, String>> list = TestSingleTonCaller
                    .getData(this.id);
            System.out.println("thread id:" + this.id + "  list > "
                    + (list == null ? "" : list.toString()));
        } catch (IOException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

这不安全,因为这种情况可能发生:

Thread 1                Thread 2
--------                --------
test instance != null
                        test instance != null
                        finds it is
finds it is
creates, assigns
                        creates, assigns
                        returns
returns

从本质上讲,这不再是单身人士了。

另请注意,您无法保证线程将返回哪个创建的实例,因为singletonInstance甚至不易变形!

轻松修复,因为你的构造函数什么都不做:

private static final SingletonCLS INSTANCE = new SingletonCLS();

public static SingletonCLS getInstance() { return INSTANCE; }

其他可能的解决方案:

  • 使用枚举;
  • 使用延迟初始化持有者类。

答案 1 :(得分:0)

首先,我认为你不需要单身人士。单例类中没有实例变量。 该方法可能非常静态。因此,它的线程安全在上下文中不需要Singleton。

其次,您的Singleton错误(如果需要)。请参阅 Effective Java Item 71。 尝试使用(lazy initialization holder class idiom)

第二次反复打开同一个文件可能不是一个好主意。更好地读取和缓存内存中的数据,然后尝试查找id。在这种情况下,您将需要一个SingleTon对象。

答案 2 :(得分:0)

您的getIntance()方法不是线程安全的。这可能导致创建多个SingletonCls对象,如上面的答案所述。 要使用延迟实例化获取类的Singleton版本,您应该使用以下代码:

public class SingletonCls 
{
    public static SingletonCls getInstance()
    {
        return LazyClass.getInstance();
    }
    private static class LazyClass
    {
        public static SingletonCls instance = new SingletonCls();
        public static SingletonCls getInstance()
        {
            return instance;
        }
    }
}

这依赖于内部类在被引用之前不会被加载的事实。这种创建Singleton类的方式称为Initialization on Demand Holder