【发布时间】:2019-01-14 18:05:42
【问题描述】:
我有一个为我的应用程序抽象弹性搜索 API 的单例包装类。
public class ElasticSearchClient {
private static volatile ElasticSearchClient elasticSearchClientInstance;
private static final Object lock = new Object();
private static elasticConfig ;
/*
** Private constructor to make this class singleton
*/
private ElasticSearchClient() {
}
/*
** This method does a lazy initialization and returns the singleton instance of ElasticSearchClient
*/
public static ElasticSearchClient getInstance() {
ElasticSearchClient elasticSearchClientInstanceToReturn = elasticSearchClientInstance;
if (elasticSearchClientInstanceToReturn == null) {
synchronized(lock) {
elasticSearchClientInstanceToReturn = elasticSearchClientInstance;
if (elasticSearchClientInstanceToReturn == null) {
// While this thread was waiting for the lock, another thread may have instantiated the clinet.
elasticSearchClientInstanceToReturn = new ElasticSearchClient();
elasticSearchClientInstance = elasticSearchClientInstanceToReturn;
}
}
}
return elasticSearchClientInstanceToReturn;
}
/*
** This method creates a new elastic index with the name as the paramater, if if does not already exists.
* Returns true if the index creation is successful, false otherwise.
*/
public boolean createElasticIndex(String index) {
if (checkIfElasticSearchIndexExists(index)) {
LOG.error("Cannot recreate already existing index: " + index);
return false;
}
if (elasticConfig == null || elasticConfig.equals(BatchConstants.EMPTY_STRING)) {
loadElasticConfigFromFile(ELASTIC_CONFIG_FILE_NAME);
}
if (elasticConfig != null && !elasticConfig.equals("")) {
try {
HttpURLConnection elasticSearchHttpURLConnection = performHttpRequest(
ELASTIC_SEARCH_URL + "/" + index,
"PUT",
elasticConfig,
"Create index: " + index
);
return elasticSearchHttpURLConnection != null &&
elasticSearchHttpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK;
} catch (Exception e) {
LOG.error("Unable to access Elastic Search API. Following exception occurred:\n" + e.getMessage());
}
} else {
LOG.error("Found empty config file");
}
return false;
}
private void loadElasticConfigFromFile(String filename) {
try {
Object obj = jsonParser.parse(new FileReader(filename);
JSONObject jsonObject = (JSONObject) obj;
LOG.info("Successfully parsed elastic config file: "+ filename);
elasticConfig = jsonObject.toString();
return;
} catch (Exception e) {
LOG.error("Cannot read elastic config from " + filename + "\n" + e.getMessage());
elasticConfig = "";
}
}
}
我有多个使用 ElasticSearchClient 的线程,如下所述
Thread1
ElasticSearchClient elasticSearchClient = ElasticSearchClient.getInstance()
elasticSearchClient.createElasticIndex("firstindex");
Thread2
ElasticSearchClient elasticSearchClient = ElasticSearchClient.getInstance()
elasticSearchClient.createElasticIndex("secondindex");
Thread3...
在我看来,单例类是线程安全的,但我不确定如果多个线程开始执行单例类的相同方法会发生什么。这有什么副作用吗?
注意:我知道上面的单例类不是反射和序列化安全的。
【问题讨论】:
-
如果多个线程同时调用
createElasticIndex("sameIndex")会发生什么?好吧,因为没有同步,所以有很多事情,但一件事可能是生成了多个 put 请求。 -
预期会有多个 put 请求。因为他们正在弹性搜索中写入不同的索引。我的全部担忧是一个线程是否会对其他线程的数据造成任何类型的数据损坏?
标签: java multithreading singleton