스레드 세이프 싱글 톤 클래스
아래 싱글 톤 클래스를 작성했습니다. 이것이 스레드로부터 안전한 싱글 톤 클래스인지 확실하지 않습니까?
public class CassandraAstyanaxConnection {
private static CassandraAstyanaxConnection _instance;
private AstyanaxContext<Keyspace> context;
private Keyspace keyspace;
private ColumnFamily<String, String> emp_cf;
public static synchronized CassandraAstyanaxConnection getInstance() {
if (_instance == null) {
_instance = new CassandraAstyanaxConnection();
}
return _instance;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}
public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}
누구든지 이것으로 나를 도울 수 있습니까? 위의 Singleton 수업에 대한 생각은 큰 도움이 될 것입니다.
업데이트 된 코드 :-
내 코드에 보헤미안 제안을 통합하려고합니다. 다음은 업데이트 된 코드입니다.
public class CassandraAstyanaxConnection {
private static class ConnectionHolder {
static final CassandraAstyanaxConnection connection = new CassandraAstyanaxConnection();
}
public static CassandraAstyanaxConnection getInstance() {
return ConnectionHolder.connection;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}
public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}
누구든지 이번에 내가 옳았는지 아닌지 살펴보고 알려줄 수 있습니까?
도와 주셔서 감사합니다.
처음 사용할 때 인스턴스가 생성되는 지연 초기화 패턴을 구현하고 있습니다.
그러나 동기화 가 필요 없는 스레드 세이프 구현을 코딩 할 수있는 간단한 트릭이 있습니다 ! 이것은 Initialization-on-demand 홀더 관용구 로 알려져 있으며 다음과 같습니다.
public class CassandraAstyanaxConnection {
private CassandraAstyanaxConnection(){ }
private static class Holder {
private static final CassandraAstyanaxConnection INSTANCE = new CassandraAstyanaxConnection();
}
public static CassandraAstyanaxConnection getInstance() {
return Holder.INSTANCE;
}
// rest of class omitted
}
이 코드는의 첫 번째 호출에서 인스턴스를 초기화하며 getInstance()
, 클래스 로더의 계약으로 인해 동기화가 필요하지 않습니다.
- 클래스 로더는 처음 액세스 할 때 클래스를로드합니다 (이 경우
Holder
의 유일한 액세스는getInstance()
메소드 내에 있음 ). - 클래스가로드 될 때 누구든지 사용할 수 있기 전에 모든 정적 이니셜 라이저가 실행되도록 보장됩니다 (즉,
Holder
정적 블록 이 실행될 때 ). - 클래스 로더에는 위의 두 지점이 스레드 안전을 보장하는 자체 동기화가 내장되어 있습니다.
게으른 초기화가 필요할 때마다 사용하는 깔끔한 트릭입니다. final
느리게 생성 되더라도 인스턴스 의 보너스도받습니다 . 또한 코드가 얼마나 깔끔하고 단순한 지 주목하십시오.
편집 : 모든 생성자를 개인 또는 보호로 설정해야합니다. 개인 생성자를 설정하고 비어 있으면 작업이 수행됩니다.
위의 모든 방법은 열심히 개체를 초기화합니다. 이건 어때. 이것은 당신이 ur 클래스를 느리게 초기화하는 데 도움이 될 것입니다. 무거운 물체가있을 수 있으며 시작시 초기화하고 싶지 않습니다.
public class MySinglton {
private MySinglton (){}
private static volatile MySinglton s;
public static MySinglton getInstance(){
if (s != null ) return s;
synchronized(MySinglton.class){
if (s == null ) {
s = new MySinglton();
}
}
return s;
}
}
아니요, pulbic 메서드에서 반환 된 값이 변경 가능한 객체 인 경우 스레드로부터 안전하지 않습니다.
이 클래스에 스레드로부터 안전한 한 가지 방법은 변경할 수 없도록 변경하는 것입니다.
이를 위해 다음과 같이이 메서드를 변경할 수 있습니다.
public Keyspace getKeyspace() {
// make a copy to prevent external user to modified or ensure that Keyspace is immutable, in that case, you don't have to make a copy
return new Keyspace( keyspace );
}
public ColumnFamily<String, String> getEmp_cf() {
// Same principle here. If ColumnFamily is immutable, you don't have to make a copy. If its not, then make a copy
return new ColumnFamily( emp_cf );
}
이 책에서 Java Concurrency in Practice 는 불변성의 원리를 볼 수 있습니다.
이 위대한 문서에서 mentiond으로 여기 :
이 문제에 대한 최선의 해결책은 정적 필드를 사용하는 [...]입니다.
public class Singelton {
private static final Singelton singleObject = new Singelton();
public Singelton getInstance(){
return singleObject;
}
}
No, this does not appear to be thread-safe. It appears that you there is mutable data accessible after the call to getInstance
, where the lock would have been released.
After java 1.5 version we can use volatile. If we used volatile java key ward, we can create singlton class with thread safe, Because instance variable share with Other thread as well.
public class SingleWithThreadSafe {
// create an object static referance of SingleWithThreadSafe with volatile
private static volatile SingleWithThreadSafe instance = null;
// if we make the constructor private so that this class cannot be
// instantiated from out side of class
private SingleWithThreadSafe() {
}
// Get only object available
public static SingleWithThreadSafe getInstance() {
if (instance == null) {
instance = new SingleWithThreadSafe();
}
return instance;
}
public void showMessage() {
System.out.println("Hello World!");
}
}
I think this will do the same thing without having to check for instance every time. static is the same as check first time
public class Singl {
private static Singl _instance;
//other vars
static{
//synchronized(Singl.class){//do not need
_instance = new Singl();
//}
}
public static Singl getInstance() {
return _instance;
}
private Singl(){
//initizlize
}
}
참고URL : https://stackoverflow.com/questions/16106260/thread-safe-singleton-class
'Program Tip' 카테고리의 다른 글
MKMapView에서 사용자 위치 주변에 반경 1000m의 원을 그립니다. (0) | 2020.12.10 |
---|---|
Magento 로그 데이터 지우기 (0) | 2020.12.09 |
PHP의 최대 실행 시간 늘리기 (0) | 2020.12.09 |
UIImage의 둥근 모서리 (0) | 2020.12.09 |
ORM 및 Embedded SQL없이 Java 웹 애플리케이션을 디자인하려면 어떻게해야합니까? (0) | 2020.12.09 |