'좋은 설계자 & 좋은관리자 & 좋은개발자/Design Pattern & Modeling'에 해당되는 글 19건

  1. 2013.12.19 Generic 이란
  2. 2013.12.19 Array Linked List 차이
  3. 2013.12.19 Static 변수와 filed 변수의 차이
  4. 2013.12.19 오버로딩 오버라이딩 차이 1
  5. 2013.12.19 프로세스와 스레드 차이
  6. 2013.12.19 Interface abstract 비교
  7. 2013.11.25 Singletone
  8. 2013.08.01 Java Object Sorting Example (Comparable And Comparator)
2013. 12. 19. 10:52

-다룰 객체를 미리 명시해줌으로써 형변환을 하지 않고 사용하는 것입니다


Posted by hoonihoon
2013. 12. 19. 10:51
Array Linked List 차이

Array:
- 동일한 자료형이고 메모리상에 연속적으로 놓인 데이터를 일괄적으로 처리하기 위해서
  만든 하나의 집합 형식으로 묶어놓은 자료구조
- 메모리 할당이 연속적이어서 인덱스 사용시 검색이 빠르다.
- 메모리 관리면에서 공간 낭비가 심하다
- 자료의 삽입 및 삭제시 성능면으로 떨어진다.


Linked List : (단순,이중(2개포인터),원형(노드의 처음과 끝이연결))
- 각 노드가 데이터와 포인터를 가지고 한줄로 연결되어 있는 방식.
- 노드의 포인터가 다음이나 이전의 노드와의 연결을 담당하게 된다
- 메모리 할당이 비연속적이며, 크기가 동적이므로 낭비가 없다
- 데이터가 많은 경우의 검색시에 처음 자료로부터 순차적으로 찾아야 하는 단점


Posted by hoonihoon
2013. 12. 19. 10:48
static변수와 field변수의 차이

- Class 당 하나만 생성되는 변수, 객체(인스턴스)를 아무리 많이 만들더라도 변수는 하나만 존재

- 객체가 생성될 때마다 새롭게 생성되는 멤버 변수와는 달리 초기에 한번만 생성되고 공유하여 사용가능

- static 변수는 객체가 생성(new)되기 전에 별도의 메모리 공간에 할당되어 초기화 된다

- static 변수가 초기화 되는 시점은 JVM에 의하여 클래스가 메모리 공간에 올라가는 순간이다.


Posted by hoonihoon
2013. 12. 19. 10:33
오버로딩과 오버라이딩 차이.  overloading overrideing

오버로딩(Overloaing)

일반적으로 하나의 클래스 안에 정의된 메소드는 이름이 중복될 수 없다.
오버로딩은 하나의 클래스에 같은 이름을 가진 메서드를 여러개 정의 할 수 있다.

단,  매개 변수의 정보가 달라야 한다. 

왜 쓸까?

동일하거나 유사한 일을 수행하는 메소드가 전달 받는 매개변수에 따라 조금씩 다른 연산을 해야 하는 경우

모든 상황에 따라 메서드 이름을 각각 정의 하는 것보다 매개변수 정보만 달리하여 동일한 이름으로 정의 한다면 코드를 작성하면

사용자 입장에서 직관적이고 편리하게 사용할 수 있다.



 


오버라이딩(Overriding)

클래스간 상속 관계에서 메소드를 재정의 하는 방법. 
오버라이딩을 할 메소드는 이름, 매개변수, 반환형이 모두 같아야 한다.


왜 쓸까?

부모클래스에 대해서 잘 알지 못하더라도 상속과 구현을 통해 이미 만들어 진 것을 사용하는 것이 가능하다.
클래스마다 다르게 구현할 필요없이, 메소드 오버라이딩을 통해서 한번에 로직을 작성하는 것이 가능하다.

이것을 다형성이라고 한다.


Posted by hoonihoon
2013. 12. 19. 10:06
프로세스와 쓰레드의 차이.  process, thread 차이

1. 
프로세스는 독립적으로 실행되며 자신만의 고유공간과 자원을 할당 받아 사용한다.
쓰레드는 한 프로세스 내에서 동작되는 여러 실행흐름 으로 프로세스 내 주소 공간이나 자원들을 대부분 공유하면서 실행된다.

2. 
프로세스는 부모 프로세스의 데이터 세그먼트의 자체 복사폰을 가지고 있다.
스레드는 그 프로세스의 데이터 세그먼트에 직접 엑세스 가능하다.

3. 
프로세스는 형제 프로세스와 통신하기 위해서 반스디 프로세스간 통신을 사용해야 한다.
스레드는 프로세스내 다른 스레드와 직접 통신 할 수 있다.

4. 
프로세스는 상당한 오버헤드가 있다.
스레드는 오버헤드가 거의 없다.
오버헤드(overhead)는 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등을 말한다. 

5. 
새로운 프로세스는 부모 프로세스의 복제를 필요로 한다.
새로운 스레드를 쉽게 만들 수 있다.

6. 
프로세스는 자식 프로세스에 대한 제어를 행사 할 수 있다.
스레드는 동일한 프로세스의 스레드를 제어 할 수 있다.

7. 
부모 프로세스에 대한 변경은 자식 프로세스에 영향을 주지 않는다.
메인 쓰레드의 변경(취소,우선순위변경 등) 은 프로세스내 다른 스레드의 행동에 영향을 미칠 수 있다.


스레드의 장점
-시스템의 throughput이 향상된다.
-시스템의 자원 소모가 줄어든다.
-프로그램 응답 시간이 단축된다.
-프로세스 간 통신 방법에 비해 스레드 간의 통신 방법이 훨씬 간단하다.

스레드의 단점
프로그램 디버깅이 어렵다.
여러개의 스레드를 이용하는 프로그램을 작성하는 경우에는 주의 깊게 설계해야 한다.

스레드간 통신시에 데이터를 주고받는 방법은 메모리 공간을 공유하므로 데이터 세그먼트, 즉 전역 변수를 이용하여 구현한다. 
그런데 전역변수를 여러 스레드가 함께 사용하려면 문제가 발생한다.  따라서 스레드 간에 통신을할 경우에는 충돌 문제가 발생하지 않도록 동기화 문제를 해결해야 한다.



그외.

프로세스는 CODE, DATA, HEAP, STACK 으로 구성 되어 있고 쓰레드는 프로세스 안에서 CODE, DATA, HEAP을 공유하고 STACK 만 별도로 가주고 있다.
프로세스간 이동 시에 비해 STACK 만을 Switching 하면 되므로 전환 속도가 빠르다.






Posted by hoonihoon
2013. 12. 19. 09:42
인터페이스 추상클래스 추상메서드의 차이

추상클래스

한개 이상 포함하고 있는 클래스, 객체(Instance) 화 할 수 없는 클래스
그리는 행위에서 삼각형,사각형,동그라미 등 공통적인 부분에 포함되어 그리다라는 추상메서드를 선언
상속을 통해 child class를 만들기 위한 parent class design 하기 위한 클래스
추상클래스는 사용해서 안해도 되지만 큰프로그램이나, 다른사람들과 비슷하게 개발한다고할때 추상클래스는 그 기본 틀을 잡아준다.(작업의 레벨 분할의 위해서 사용)


abstract class Player{
          public abstract void start();
}
public class Radio extends Player{
          @Override public void start() {}
}

추상메소드

추상메서드는 메서드의 구현부분(몸통)이 없고, 메서드 선언부분만 존재
추상메서드는 몸통이 없으므로 직접 어떤일을 할 수가 없다.



인터페이스

인터페이스는 단일 상속의 확장성 문제를 보완하는 기능을 함.
상수와 추상메소드의 집합체
-모든 멤버 변수는 public static final 이여야 하며 이를 생략 할 수 있다.
-모든 메소드는 public absctract 이어야 하며 이를 생략 할 수 있다.
서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
인터페이스를 구현할때, 클래스는 반드시 인터페이스가 요구하는 모든 메소드를 구현
중복구현가능
공동 작업을 위한 상호간의 인터페이스를 위해 사용


[Sample]  Sample 출저: http://rank01.tistory.com/63

public interface Card(){

private int spade = 5; //오류 : interface 제약을 따르지 않았다.

public int spade1 = 5; //정상 : public static final spade1 = 5; 로 컴파일러가 자동으로 추가해준다.

static int heard = 2;  //정상 : 컴파일러의 자동추가

int clover = 4; //정상 : 컴파일러의 자동추가

 

public abstract String getCardNumber(); //제약을 따랐기 때문에 정상이다.

String getCardKing(); //public abstract String getCardKing(); 컴파일러가 자동으로 추가해준다.

 

private abstract String getCard(); //제약을 따르지 않은  private로 오류가 난다.

protected abstract String getCard2(); //제약을 따르지 않은 protected로 오류가 난다.

 

     }



내가 찾던 인터페이스 

인터페이스는 클래스를 서로 연결시켜주는 매개체와 같은 역할을 하면서

자신을 구현한 클래스에 대해 명령(수행) 을 내일수 있습니다.

 

 

class Html implements WebIF {}

 

class Xml implements WebIF {}

 

class Pdf implements WebIF {}

 

위의 Html Xml Pdf  세가지의 클래스는 웹 인터페이스를 구현 하였습니다.

 

 

그러므로 위의 3개의 클래스의 형(Class Type)은 같습니다.

 

샘플 코드를 작성하면 이렇게 되겠지요

 

WebIF inf = new Html();

 

WebIF inf = new Xml();

 

WebIF inf = new Pdf();

 

업 케스팅 인스턴스를 한 것입니다.

 

그런데 WebIf 에 print() 메서드가 있다면

 

Html

Xml

Pdf

 

위의 3개의 클래스는 prin() 메서드를 자신들에 알맞게 구현해 주면 됩니다.

 

Html 은 <html></html> 이 될 것이고

Xml 은 이 될 것이고

Pdf 는 %PDF-1.2 ..................... %%EOF 가 되겠지요...

 

인터페이스는 서로다른 객체를 표준화된 인터페이스란 통로로 서로 연결시키고

 

약속된 일을 수행함으로써 확장된 객체로서 다양한 비지니스 요구사항을 충족시키게 되는 것입니다.


출저: http://kin.naver.com/qna/detail.nhn?d1id=1&dirId=1040201&docId=69965713

Posted by hoonihoon
2013. 11. 25. 10:07

프로그램에서 단 하나의 인스턴스(Instance)만 존재하게 하고 싶을 때 사용하는 패턴입니다.
어디서든지 그 인스턴스에 접근할 수 있기 때문에 전역 변수 등을 관리할 때 상당히 편리합니다.


싱글톤 패턴의 간단한 예는 다음과 같습니다. (다만, 아래의 코드는 멀티 쓰레드 환경에서 문제가 발생합니다.)

01.public class MyClass
02.{
03.private static MyClass m_MyClass = null;
04. 
05.private MyClass() {}
06. 
07.public static MyClass getInstance()
08.{
09.if (m_MyClass == null)
10.{
11.m_MyClass = new MyClass();
12.}
13. 
14.return m_MyClass;
15.}
16.}
위와 같은 경우는 멀티 쓰레드(Multi-Thread) 환경에서는 getInstace() 메소드가 끝나기 전에
각각의 쓰레드에서 접근이 가능하기 때문에 운이 없으면 인스턴스가 여러 개 생성될 수도 있습니다.


이 경우 해결 방법은 getInstance() 메소드를 synchronized로 동기화시키는 방법이 있습니다.
01.public static synchronized MyClass getInstance()
02.{
03.if (m_MyClass == null)
04.{
05.m_MyClass = new MyClass();
06.}
07. 
08.return m_MyClass;
09.}
하지만, 함수 전체에 synchronized는 동기화 과정에서 속도 문제가 발생할 수 있습니다.


좀 더 효과적으로 하려면 함수 전체에 synchronized를 거는 것이 아니라 함수 내부의 특정 구간에만 거는 방법입니다.
01.public static MyClass getInstance()
02.{
03.if (m_MyClass == null)
04.{
05.synchronized(MyClass.class)
06.{
07.if (m_MyClass == null)
08.{
09.m_MyClass = new MyClass();
10.}
11.}
12.}
13. 
14.return m_MyClass;
15.}


그리고 코드를 좀 더 깔끔하고 쉽게 가져가기 위해서는
 아예 처음부터 인스턴스를 생성해버리는 방법입니다.
01.public class MyClass
02.{
03.private static MyClass m_MyClass = new MyClass();
04. 
05.private MyClass() {}
06. 
07.public static MyClass getInstance()
08.{
09.return m_MyClass;
10.}
11.}
이 경우는 프로그램이 처음 실행되면서 바로 인스턴스가 생겨버리기 때문에 불필요한 부분에서 인스턴스가
메모리를 차지해버린다는 단점이 있지만, 멀티 쓰레드 동기화 문제에서 자유로울 수 있고 코드가 간결해진다는
장점이 있습니다. 

그리고 어차피 한 번은 메모리에 올라갈 인스턴스이기 때문에 미리 메모리에 실어 놓는 것도 나쁘지는 않겠죠. ^^; 

출처 - http://snowbora.com/442

=======================================================================

Singleton Pattern - 디자인 패턴

패턴 정의 #6 - Singleton Pattern

1. synchronized 키워드를 사용한다.

  1. public class Singleton {  
  2.     private static Singleton uniqueInstance;  
  3.    
  4.     // other useful instance variables here  
  5.    
  6.     private Singleton() {}  
  7.    
  8.     public static synchronized Singleton getInstance() {  
  9.         if (uniqueInstance == null) {  
  10.             uniqueInstance = new Singleton();  
  11.         }  
  12.         return uniqueInstance;  
  13.     }  
  14.    
  15.     // other useful methods here  
  16. }  

2. 인스턴스를 필요할 때 생성하지 말고, 처음부터 만들어 버린다.

  1. public class Singleton {  
  2.     private static Singleton uniqueInstance = new Singleton();  
  3.    
  4.     private Singleton() {}  
  5.    
  6.     public static Singleton getInstance() {  
  7.         return uniqueInstance;  
  8.     }  
  9. }  

3. DCL(Double Checking Locking)을 써서 getInstance()에서 동기화 되는 부분에 대한 체크를 줄입니다.

  1. public class Singleton {  
  2.     private volatile static Singleton uniqueInstance;  
  3.    
  4.     private Singleton() {}  
  5.    
  6.     public static Singleton getInstance() {  
  7.         if (uniqueInstance == null) {  
  8.             synchronized (Singleton.class) {  
  9.                 if (uniqueInstance == null) {  
  10.                     uniqueInstance = new Singleton();  
  11.                 }  
  12.             }  
  13.         }  
  14.         return uniqueInstance;  
  15.     }  
  16. }  

I. Singleton 이란?

아마 GOF의 32가지 패턴 중 가장 쉬우면서도 가장 자주 쓰이게 되며, 가장 문제가 될 소지를 가지는 패턴을 말하면 Singleton을 말할 수 있지 않을까 합니다.

먼저 Singleton 패턴의 용도는 하나의 프로그램 내에서 하나의 인스턴스만을 생성해야만 하는 상황. 예를 들어 환경설정을 관리하는 클래스나
Connection Pool, Thread Pool과 같이 풀(Pool) 형태로 관리되는 클래스의 경우 프로그램 내에서 단 하나의 인스턴스로 관리되는 것이 일반적이며, 이 때 Singleton 패턴을 적용하는 것이 일반적인 경우라고 볼수 있겠습니다. 그럼 세부적인 구현 형태를 살펴 보도록 하겠습니다.

II. Singleton 구현

Singleton 패턴의 가장 일반적인 형태는 다음과 같습니다.

singleton.bmp 

<일반적인 Singleton class diagram>

중요하게 보아야 할 곳은 생성자가 private으로 선언되어 있다는 것이죠. 이유는 간단하게도 클래스 외부에서 이 클래스를 직접 new 키워드로 생성하지 못하게 막겠다는 의미가 되겠습니다. Singleton 패턴은 설명보다는 코드로 보는 것이 훨씬 간결하므로 다음 코드를 보도록 하겠습니다.

  1. Singleton 패턴 

  2. class Singleton { 

  3. private static Singleton instance;

  4. private Singleton(){ 

  5. public static Singleton getInstance(){ 

  6. if (instance == null) 

  7. instance = new Singleton();  

  8. return instance; 

  9. }

 

   위 코드에서 파란색으로 표기된 선언부에 집중해야 합니다. Singleton 클래스의 인스턴스를 외부에서 사용하기 위해서는 항상 getInstance 메소드를 호출해야만 하도록 강제된 것을 확인하실 수 있습니다.  위와 같은 경우 getInstance가 호출될 때 객체가 생성되는데 최초 로딩 시에 객체를 생성해 두는 것이 효율적인 경우에는 다음과 같이 멤버 변수를 선언하는 곳에서 직접 생성하는 방법을 이용할 수 있습니다.

 

  1. ClassLoader에 의해 미리 인스턴스를 생성하는 방법 
  2. class Singleton { 
  3. private static Singleton instance = new Singleton(); 
  4. private Singleton(){} 
  5. public static Singleton getInstance(){ 
  6. if (instance == null) 
  7. instance = new Singleton(); 
  8. return instance; 

위의 코드에서 붉은색으로 표기된 멤버 변수 선언부를 보면 new 키워드에 의해 static으로 선언된 멤버 변수의 인스턴스를 미리 생성하는 것을 볼 수 있습니다.

다중 쓰레드 프로그래밍에 필요한 것이 아니라면 위의 코드만으로도 완성된 코드라고 볼수 있겠습니다. 미리 인스턴스를 생성할 필요가 없는 경우에는 이전의 방법을 이용하는데 그런한 방식을 lazy(게으른) 방식이라고 이야기 합니다.

다중 쓰레드 프로그래밍에서는 동기화를 이용한 적절한 수정이 필요한데 많은 커뮤니티에서 그에 따른 예제 코드가 잘 나와있습니다.

(Singleton의 다양한 형태 : http://www.anfamily.net/mcsong/70)

위의 블로그에 방문하시면 싱글톤 패턴의 다양한 종류와 그에 따른 장단점이 잘 분류되어 있습니다.

다만 좀더 자세히 내용을 들여다 보면 가장 간단한 방법이 오히려 득이 되는 경우를 찾을 수 있을 것 입니다. 다음 코드를 봐주세요.

  1. Instance의 생성은 단 한번만

  2. class Singleton{

  3. private static Singleton instance = new Singleton();

  4. private Singleton(){}

  5. public static Singleton getInstance(){

  6. return instance;

  7. }

  8. }

위의 코드의 녹색으로 표시된 부분을 봐주세요. Simple is best 라는 말 처럼 위의 코드는 Thread-safe하게 잘 만들어진 코드라고 할 수 있겠습니다.

이 클래스는 전체 라이프 타임 중에서 단 한번만 객체를 생성하고 다시는 생성하지 않습니다. 여러개의 쓰레드가 접근을 한다고 하더라도 인스턴스가 두개 이상 생성되거나 Null값을 리턴 받을 염려도 생성자가 두번 호출 되는 경우도 없죠. 

 

III. 결론

하나의 패턴은 다양한 형태로 표현되는 경우가 많습니다. 어쩔 때는 경계가 모호한 형태로 패턴이 구현되는 경우도 있지요.

이번 싱글톤 패턴은 목적과 형태가 분명한 패턴으로 항상 머리에 넣어두고 사용해야할 중요한 패턴이라고 말할 수 있습니다.

 

참고문헌


출처 -  http://sakula99.egloos.com/2971297 
 

===================================================================================


싱글톤(Singleton) Pattern 이란?



객체지향형언어(OOP)에 대해 조금이라도 파고든 사람이라면 싱글톤 패턴이라는 

말을 들어봤을 것이다. 못들어봤다면 이제부터 들었다고 해라. 싱글톤이란 생성하고자 

하는 인스턴스의 수를 오직 하나로 제한하는 디자인 패턴이다.



그렇다면 왜 싱글톤 패턴을 사용해야하는 것일까? 라는 질문에 대게 답하는 것이

여러개의 인스턴스를 생성하게 되면 가끔 프로그래머도 당혹스럽게 되는 서로의

인스턴스에 간섭을 하는 경우가 있다. 정말 재수 없는 일이 아닐 수가 없다.





public class Singleton

{

private static Singleton singleton = new Singleton();

protected Singleton()

{

System.out.println("Maked Singleton");

}

public static Singleton getInstance()

{

return singleton;

}

}



싱글톤의 기본형이다. singleton 멤버변수는 static 이어야한다는 것과 Singleton 클래스의

생성자는 private / protected 이어야한다는 것을 꼭 유념해야한다. private 일 경우는 결코

new 를 이용하여 인스턴스의 중복 생성을 방지하는 셈이기도 하나 상속이 되지 않는다는

단점이 있어 protected로 대게 선언한다.



뭐~ 싱글톤 패턴이 만들어졌나 아닌가 확인할 것이라면 Test 클래스를 만들어보자.



public class Test

{

public static void main(String [] args)

{

System.out.println("Singleton pattern");

Singleton sg1=Singleton.getInstance();

Singleton sg2=Singleton.getInstance();

if( sg1 == sg2 )

{

System.out.println("Equal");

}

else

{

System.out.println("Not Equal");

}

}

}



여기서 보면 Singleton 의 인스턴스를 생성하기 위해 getInstance() 메소드를 이용한다.

왜 그럴까? Singleton 클래스의 private static Singleton singleton = new Singleton(); 

부분을 유심히 바라보기 바란다. 이 singleton은 static으로 선언된다. 즉 하나의 인스턴스

singleton 만 생성하는 셈이다. 아마 결과도 Equal로 출력될 것이다.


출처 - http://coolx.net/cboard/read.jsp?db=develop&mode=read&num=261

출저 : linuxism.tistory.com/14



싱글톤 패턴의 여러형태  개발 / Study 

2010/02/09 11:34

복사http://blog.naver.com/k1qpo/99745837

전용뷰어 보기

아래 내용은 OKJSP에서 발췌를 하였습니다..
소스코드내에는 몇가지 싱글톤 구현방법이 나옵니다. 그 각각이 의미하는바는 다음과 같습니다.

1) EagerSingleton

  1. static class EagerSingleton extends Singleton {  
  2.   static final EagerSingleton theInstance = new EagerSingleton();  
  3.   static EagerSingleton getInstance() {  
  4.   return theInstance;  
  5.   }  
  6. }  

이 경우는 미리 싱글톤 인스턴스를 생성하는 방법으로 static final 필드에 인스턴스를 생성하여 할당하는 방법입니다. 이 필드는 클래스로더에 의해서 EagerSingleton이 메모리로 올라오는 순간에 안전하게(thread-safe하게)초기화 됩니다. 이 방법이 아마 성능이 가장 우수하게 나타날 것입니다. 
장점은 동기화부담이 적다는 것입니다. 단 한번 클래스로더가 thread-safe하게 클래스를 로드하는 시점에 클래스가 로딩되어 안전합니다. 단점은 인스턴스가 미리부터 생성된다는 것입니다. 

2) SynchedSingleton
  1. static class SynchedSingleton extends Singleton {  
  2.   static SynchedSingleton theInstance;  
  3.   static synchronized SynchedSingleton getInstance() {  
  4.    if (theInstance == null)  
  5.      theInstance = new SynchedSingleton();  
  6.    return theInstance;  
  7.   }  
  8. }  

이 방법은 싱글톤 필드에 접근할때마다 동기화를 수행하는 방법입니다. 매번 동기화를 수행하므로 자바 메모리 모델에 따른 각종 문제를 방지할 수 있어 thread-safe합니다. 단점은 매번동기화를 수행하므로 수행 비용이 높다는 것입니다.

3) ThreadLocalSingleton
  1. static class ThreadLocalSingleton extends Singleton {  
  2.   static final ThreadLocal perThreadInstance = new ThreadLocal();  
  3.   static final Object lock = new Object();  
  4.   static ThreadLocalSingleton theInstance;  
  5.   
  6.   static ThreadLocalSingleton getInstance() {  
  7.   ThreadLocalSingleton instance = (ThreadLocalSingleton)(perThreadInstance.get());  
  8.   if (instance == null) {  
  9.      synchronized(lock) {  
  10.        instance = theInstance;  
  11.        if (instance == null)  
  12.          instance = theInstance = new ThreadLocalSingleton();  
  13.      }  
  14.      // copy global to per-thread  
  15.      perThreadInstance.set(instance);  
  16.    }  
  17.      return instance;  
  18.   }  
  19. }  

이 방법은 Thread Local Storage를 사용한 해법입니다. 자바 쓰레드 메모리 모델에서 문제가 발생하는 것은 멀티 CPU상황에서 각각의 CPU가 자신의 캐시내에 클래스의 필드를 복사해넣는다는 것입니다. 이러한 캐시는 메인메모리와 동기화가 되어 있지 않습니다. 즉, 각각의 CPU가 하나의 클래스를 접근하게되면 각각의 CPU는 그 클래스의 내용을 다르게 볼 수 있다는 것입니다. 
싱글톤을 구현하면 instance라는 필드를 여러개의 CPU가 참조하는데 이 필드를 여러개의 CPU가 다르게 보게 됩니다. 예를들어 CPU A가 인스턴스를 생성하고 생성한 인스턴스를 instance에 할당한다고 합시다.
그러면 CPU A가 또다시 이 instance 필드를 참조할때는 생성된 인스턴스를 제대로 보게 됩니다. 그러나 CPU B가 이 instance필드를 참조할때는 instance필드가 null로 나타날 수 있습니다. 그 이유는 CPU A가 수행한 작업은 synchronized블록을 통과할때까지 메인메모리에 반영이 안되고 자신의 캐시내에만 담겨 있을 수 있으며, CPU B역시 synchornized블록을 통과하지 않으면 메인메모리가 아닌 자신의 캐시만
들여다보기 때문입니다.

이를 해결하려면 각각 CPU가 동기화블록을 들어갔다가 나와야만 하는데, 이를 구현한 것이 위의 코드입니다. 각각의 Thread는 자신만의 메모리공간으로서 TLS(Thread Local Storage)를 가지고 있으며 이들은 매 쓰레드마다의 공간이므로 동기화될 필요가 없습니다. 따라서 이 저장소에 해당 쓰레드가 synchronized블록을 한번이라도 다녀왔는지(한번이라도 다녀오면 CPU가 메인메모리의 값을 가져오니까요)를
저장해둡니다.

4) SimulatedThreadLocalSingleton
  1. static class SimulatedThreadLocalSingleton extends Singleton {  
  2.   static SimulatedThreadLocalSingleton theInstance;  
  3.   static final Object lock = new Object();  
  4.   static final Object key = new Object();  
  5.   
  6.   static Singleton getInstance() {  
  7.   TSS t = (TSS)(Thread.currentThread());  
  8.   Singleton instance = (Singleton)(t.threadLocalHashtable.get(key));  
  9.   if (instance == null) {  
  10.      synchronized(lock) {  
  11.        instance = theInstance;  
  12.        if (instance == null)  
  13.          instance = theInstance = new SimulatedThreadLocalSingleton();  
  14.      }  
  15.      // copy global to per-thread  
  16.      t.threadLocalHashtable.put(key, instance);  
  17.   }  
  18.   return instance;  
  19.   }  
  20. }  

이 방법은 TLS를 ThreadLocal 클래스를 쓰지 않고 직접구현한 방식입니다.

5) VolatileSingleton

  1. static class VolatileSingleton extends Singleton {  
  2.   static final Object lock = new Object();  
  3.   static volatile VolatileSingleton theInstance;  
  4.   
  5.   static VolatileSingleton getInstance() {  
  6.      VolatileSingleton instance = theInstance;  
  7.      if (instance == null) {  
  8.        synchronized(lock) {  
  9.         instance = theInstance;  
  10.         if (instance == null)  
  11.           instance = theInstance = new VolatileSingleton();  
  12.       }  
  13.     }  
  14.   return instance;  
  15.   }  
  16. }  

주의!)이 방법은 절대로 사용해서는 안됩니다. 
이 방법은 volatile를 사용합니다. volatile 로 선언된 필드는 매번 원자적으로 쓰레드 safe하게 이루어집니다. 즉 각각의 변수에 대한 접근이 매번 메인메모리와 동기화될 뿐만아니라, thread safe하게 이루어집니다. synchronized와 volatile은 이처럼 변수의 접근마다 동기화를 하느냐 아니면 특정 블록을 통채로 동기화
하는냐의 문제에 있어서 접근방법이 틀립니다. 그러나 아쉽게도 volatile은 대부분의 자바 컴파일러에서 제대로 구현되어있지않으며 따라서 사용하는것을 권하지 않습니다. SUN의 컴파일러는 제대로 되지 않느냐 하고 생각하실 수 있지만 전혀 안그렇습니다. SUN의 JDK 1.3대에서도 제대로 구현이 되어있지 않습니다.
volatile은 동기화의 문제를 비롯한 다양한 암시적 작동이 보장되어야하는데 이를 제대로 책임지고 않기때문입니다.

6) DirectThreadFieldSingleton
  1. static class DirectThreadFieldSingleton extends Singleton {  
  2. static DirectThreadFieldSingleton theInstance;  
  3. static final Object lock = new Object();  
  4.   
  5. static Singleton getInstance(TSS t) {  
  6.   Singleton instance = t.singleton;  
  7.   if (instance == null) {  
  8.     synchronized(lock) {  
  9.       instance = theInstance;  
  10.       if (instance == null)  
  11.         instance = theInstance = new DirectThreadFieldSingleton();  
  12.     }  
  13.     // copy global to per-thread  
  14.     t.singleton = instance;  
  15.   }  
  16.   return instance;  
  17. }  
  18. }  

인스턴스를 할당받고자하는 쪽에서 TSS라는 형태의 클래스를 쓰레드마다 할당한채로 갖고 있다가 이것을 싱글톤 클래스에 넘깁니다. 그러면 TSS.singleton변수의 값을가지고 동기화 수행여부를 결정하는 방식입니다. ThreadLocal의 변형이며, 모든 인스턴스를 획득하고자하는 쓰레드가 TSS를 넘겨야한다는 점에서
좋은 방법은 아니겠죠.

7) ThreadFieldSingleton
  1. static class ThreadFieldSingleton extends Singleton {  
  2. static final Object lock = new Object();  
  3. static ThreadFieldSingleton theInstance;  
  4.   
  5. static Singleton getInstance() {  
  6.   TSS t = (TSS)(Thread.currentThread());  
  7.   Singleton instance = t.singleton;  
  8.   if (instance == null) {  
  9.     synchronized(lock) {  
  10.       instance = theInstance;  
  11.       if (instance == null)  
  12.         instance = theInstance = new ThreadFieldSingleton();  
  13.     }  
  14.     // copy global to per-thread  
  15.     t.singleton = instance;  
  16.   }  
  17.   return instance;  
  18. }  
  19. }  

이 방법역시 ThreadLocal의 구현에 대한 변형된 구현입니다. ThreadLocal 대신, 특정 싱글톤 클래스에 대한 인스턴스를 획득하려고 시도하는 쓰레드를 캐스팅해서 ThreadLocal을 구현한 것이죠. 개인적으로 이 방법은 별로 좋지 않다고봅니다. 특정 클래스의 인스턴스를 획득하려면 쓰레드가 어떠한 인스턴스를 구현하고 있는지는 쉽사리 가정하기가 곤란하죠.


Posted by hoonihoon
2013. 8. 1. 18:45

In this tutorial, it shows the use of java.lang.Comparable and java.util.Comparator to sort a Java object based on its property value.

1. Sort an Array

To sort an Array, use the Arrays.sort().

	String[] fruits = new String[] {"Pineapple","Apple", "Orange", "Banana"}; 
 
	Arrays.sort(fruits);
 
	int i=0;
	for(String temp: fruits){
		System.out.println("fruits " + ++i + " : " + temp);
	}

Output

fruits 1 : Apple
fruits 2 : Banana
fruits 3 : Orange
fruits 4 : Pineapple

2. Sort an ArrayList

To sort an ArrayList, use the Collections.sort().

	List<String> fruits = new ArrayList<String>();
 
	fruits.add("Pineapple");
	fruits.add("Apple");
	fruits.add("Orange");
	fruits.add("Banana");
 
	Collections.sort(fruits);
 
	int i=0;
	for(String temp: fruits){
		System.out.println("fruits " + ++i + " : " + temp);
	}

Output

fruits 1 : Apple
fruits 2 : Banana
fruits 3 : Orange
fruits 4 : Pineapple

3. Sort an Object with Comparable

How about a Java Object? Let create a Fruit class:

public class Fruit{
 
	private String fruitName;
	private String fruitDesc;
	private int quantity;
 
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
 
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
}

To sort it, you may think of Arrays.sort() again, see below example :

package com.mkyong.common.action;
 
import java.util.Arrays;
 
public class SortFruitObject{
 
	public static void main(String args[]){
 
		Fruit[] fruits = new Fruit[4];
 
		Fruit pineappale = new Fruit("Pineapple", "Pineapple description",70); 
		Fruit apple = new Fruit("Apple", "Apple description",100); 
		Fruit orange = new Fruit("Orange", "Orange description",80); 
		Fruit banana = new Fruit("Banana", "Banana description",90); 
 
		fruits[0]=pineappale;
		fruits[1]=apple;
		fruits[2]=orange;
		fruits[3]=banana;
 
		Arrays.sort(fruits);
 
		int i=0;
		for(Fruit temp: fruits){
		   System.out.println("fruits " + ++i + " : " + temp.getFruitName() + 
			", Quantity : " + temp.getQuantity());
		}
 
	}	
}

Nice try, but, what you expect the Arrays.sort() will do? You didn’t even mention what to sort in the Fruit class. So, it will hits the following error :

Exception in thread "main" java.lang.ClassCastException: 
com.mkyong.common.Fruit cannot be cast to java.lang.Comparable
	at java.util.Arrays.mergeSort(Unknown Source)
	at java.util.Arrays.sort(Unknown Source)

To sort an Object by its property, you have to make the Object implement the Comparable interface and override thecompareTo() method. Lets see the new Fruit class again.

public class Fruit implements Comparable<Fruit>{
 
	private String fruitName;
	private String fruitDesc;
	private int quantity;
 
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
 
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
 
	public int compareTo(Fruit compareFruit) {
 
		int compareQuantity = ((Fruit) compareFruit).getQuantity(); 
 
		//ascending order
		return this.quantity - compareQuantity;
 
		//descending order
		//return compareQuantity - this.quantity;
 
	}	
}

The new Fruit class implemented the Comparable interface, and overrided the compareTo() method to compare its quantity property in ascending order.

The compareTo() method is hard to explain, in integer sorting, just remember

  1. this.quantity – compareQuantity is ascending order.
  2. compareQuantity – this.quantity is descending order.

To understand more about compareTo() method, read this Comparable documentation.

Run it again, now the Fruits array is sort by its quantity in ascending order.

fruits 1 : Pineapple, Quantity : 70
fruits 2 : Orange, Quantity : 80
fruits 3 : Banana, Quantity : 90
fruits 4 : Apple, Quantity : 100

4. Sort an Object with Comparator

How about sorting with Fruit’s “fruitName” or “Quantity”? The Comparable interface is only allow to sort a single property. To sort with multiple properties, you need Comparator. See the new updated Fruit class again :

import java.util.Comparator;
 
public class Fruit implements Comparable<Fruit>{
 
	private String fruitName;
	private String fruitDesc;
	private int quantity;
 
	public Fruit(String fruitName, String fruitDesc, int quantity) {
		super();
		this.fruitName = fruitName;
		this.fruitDesc = fruitDesc;
		this.quantity = quantity;
	}
 
	public String getFruitName() {
		return fruitName;
	}
	public void setFruitName(String fruitName) {
		this.fruitName = fruitName;
	}
	public String getFruitDesc() {
		return fruitDesc;
	}
	public void setFruitDesc(String fruitDesc) {
		this.fruitDesc = fruitDesc;
	}
	public int getQuantity() {
		return quantity;
	}
	public void setQuantity(int quantity) {
		this.quantity = quantity;
	}
 
	public int compareTo(Fruit compareFruit) {
 
		int compareQuantity = ((Fruit) compareFruit).getQuantity(); 
 
		//ascending order
		return this.quantity - compareQuantity;
 
		//descending order
		//return compareQuantity - this.quantity;
 
	}
 
	public static Comparator<Fruit> FruitNameComparator 
                          = new Comparator<Fruit>() {
 
	    public int compare(Fruit fruit1, Fruit fruit2) {
 
	      String fruitName1 = fruit1.getFruitName().toUpperCase();
	      String fruitName2 = fruit2.getFruitName().toUpperCase();
 
	      //ascending order
	      return fruitName1.compareTo(fruitName2);
 
	      //descending order
	      //return fruitName2.compareTo(fruitName1);
	    }
 
	};
}

The Fruit class contains a static FruitNameComparator method to compare the “fruitName”. Now the Fruit object is able to sort with either “quantity” or “fruitName” property. Run it again.

1. Sort Fruit array based on its “fruitName” property in ascending order.

Arrays.sort(fruits, Fruit.FruitNameComparator);

Output

fruits 1 : Apple, Quantity : 100
fruits 2 : Banana, Quantity : 90
fruits 3 : Orange, Quantity : 80
fruits 4 : Pineapple, Quantity : 70

2. Sort Fruit array based on its “quantity” property in ascending order.

Arrays.sort(fruits)

Output

fruits 1 : Pineapple, Quantity : 70
fruits 2 : Orange, Quantity : 80
fruits 3 : Banana, Quantity : 90
fruits 4 : Apple, Quantity : 100
The java.lang.Comparable and java.util.Comparator are powerful but take time to understand and make use of it, may be it’s due to the lacking of detail example.

My thoughts…

In future, Arrays class should provides more generic and handy method – Arrays.sort(Object, String, flag).

To sort a object array by its “fruitName” in ascending order.

Arrays.sort(fruits, fruitName, Arrays.ASCENDING);

To sort a object array by its “quantity” in ascending order.

Arrays.sort(fruits, quantity, Arrays.DESCENDING);

Reference

  1. Comparable documentation
  2. Comparator documentation


Posted by hoonihoon