0

以下のクラスを見て、以下のコードがスレッドセーフかどうか教えてください。static私の質問のポイントは、そのメソッドとそのメソッドがシングルトン インスタンスのメソッドを呼び出す1 つのクラスです。また、staticメソッドはインスタンスによって呼び出されRunnableます。だから私は皆さんにコードを確認するようにお願いしています -staticメソッドとそれはマルチスレッド環境でシングルトンのメソッドを呼び出します - 安全ですか?

私の質問に答えていただければ幸いです。

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();
        }
    }
}
4

3 に答える 3

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; }

その他の可能な解決策:

  • 列挙型を使用します。
  • 遅延初期化ホルダー クラスを使用します。
于 2013-07-04T16:02:35.263 に答える
0

まず第一に、ここではシングルトンは必要ないと思います。シングルトン クラスにインスタンス変数がありません。メソッドは非常に静的である可能性があります。したがって、シングルトンが必要ないコンテキストでスレッドセーフです。

次に、Singleton が間違っています (必要な場合)。有効な Java 項目 71を参照してください。 (lazy initialization holder class idiom) を使用してみてください

第二に、同じファイルを何度も開くのは得策ではないかもしれません。メモリ内のデータを読み取ってキャッシュしてから、ID を見つけてみてください。この場合、SingleTon オブジェクトが必要になります。

于 2013-07-04T16:34:22.757 に答える