Egloos | Log-in


태그 : 자바

프리마커 문법

http://freemarker.org/docs/index.html

FreeMarker는 Velocity와 마찬가지로 templating 언어이다.
우리가 Jsp를 코딩하다보면 날코딩으로 생산성이 떨어진다. 그래서 우리는 좀더 편리하게 사용하기위해서 템플릿 엔진을 사용한다.
그리고 가장 큰 장점은 아래의 1번에서 보듯이 매크로 기능으로 기능을 만들어서 사용할 수 있다는 점이다.
다음은 FreeMarker의 사용 방법을 기술했다.
FTL tag
<# >


주석
<#--주석달기-->


반복문
1.
<#list [Object code에서 key값 ]  as  [별칭할 값]>
 
2. for(int i=0;i<10;i++)
<#list  1..10  as i >
      ${i}
   <#assign i=i+1?int>
 
3. 사이즈를 알고 싶을때.. Key 값이 list 인 경우
 
<#assign size=list?size>
 
4. 다른 변수로 정의하고 싶을때에는
<#setting [새로]=[기존]>

 
5. 변수선언
<#assign x=0>   <#--x에 0를 할당해 준것이다. -->
x값을 출력하고자 할때 --> ${x}


6. <#macro green>
“<@green>”이런식으로 쓴다.
주로 변하지 않는 변수를 이렇게 선언해서 쓴다.
 
7. 조건문
<#if>
 
8. int형으로 선언해 주고 싶은때에는
<#assign x=0 ? int>
 

1. @macro
- 프리마커 템플릿 전역에서 공통으로 사용되는 UI 디펜던트한 함수는 매크로로 만들어 여러 ftl에서 사용할 수 있도록 해준다. 샘플을 참고하도록 한다.
- 형식 : <@매크로명 변수1, 변수2, ... />
- 샘플1) 긴 문자열을 적당한 크기로 자르는 기능의 매크로
*사용법 : <@trimX ${item.title}, 20 />
*매크로 :
<#macro trimX src max><#compress>
<#if src?length &gt; max>
${src[0..max-1]}..
<#else>
${src}
</#if>
</#compress></#macro>

 

- 샘플2) YYYYMMDD 형식의 문자열을 YYYY.MM.DD 형식으로 변환하는 매크로
*사용법 : <@parseDay ${item.regdate} />
*매크로 :
<#macro parseDay src><#compress>
<#if src?length == 8>
${src[0..3]}.${src[4..5]?number}.${src[6..7]?number}
<#else>
${src}
</#if>
</#compress></#macro>

 

2. #list
- 배열 형식의 오브젝트를 루핑 처리할때 사용하는 프리마커 지시자이다. “로컬엘리어스_index” 라는 변수는 0부터 시작하는 시퀀스번호이다.
- 형식 : <#list 배열객체 as 로컬엘리어스명></#list>
- 샘플1)
<#list LIST as item>
번호 : ${item_index+1} | 이름 : ${item.name} | 아이디 : ${item.id}
</#list>

 

3. #if
- 프리마커 조건문에 사용되는 지시자이다.
- 형식 : <#if 조건식></#if>
- 샘플1) string 비교
<#if ENTITY.usergrade == “A” >......</#if>
- 샘플2) number 비교
<#if ENTITY.userclass?number == 3>.....</#if>
- 샘플3) boolean 비교
<#if ENTITY.isAuth()>.....</#if>

 

4. #break
- Loop문을 중단하고 다음 스크립트로 넘어가려고 할때 사용되는 지시자이다.
- 형식 : <#break>
- 샘플1) 루프문을 실행하는 중 5번째에서 escape 하는 예
<#list LIST as item>
<#if item_index &gt; 3><#break></#if>
</#list>

 

5. #assign
- 프리마커내에서 사용자 정의 로컬변수가 필요할 때 사용하는 지시자이다.
- 형식 : <#assign 로컬변수명 = 초기화값>
- 샘플1) <#assign CHECK = item_index>

 

6. [x...y]
- 문자열의 일정 범위를 자를때 사용하는 함수
- 형식 : ${문자열[1..5]}
- 샘플1) ${item.name[1..5]}

 

7. ?has_content
- 리스트형 오브젝트가 null이 아니고 최소 1개 이상의 컨텐츠를 가지고 있는지 체크하는 함수로써 ?has_content는 ?exists와 ?size>0 두가지 체크를 동시에 해주는 함수이다.
- 형식 : 리스트오브젝트?has_content
- 샘플1) <#if LIST?has_content>.....</#if>

 

8. ?exists
- NULL체크 함수. if_exists는 <#if 지시자 없이도 사용할 수 있게 해주는 표현식이다.
- 형식 : 오브젝트?exists
- 샘플1) <#if ENTITY.username?exists>${ENTITY.username?substring(0, 5)}</#if>
- 샘플2) <#if LIST?exists && LIST?size &gt; 0>.....</#if>
- 샘플3) ${ENTITY.username?if_exists}

 

9. ?default
- NULL값을 대체해주는 함수
- 형식 : 오브젝트?default(디폴트값)
- 샘플1) ${item.userclass?default(“99”)}
- 샘플2) ${item.age?default(20)}

 

10. ?string
- 문자열로 형변환하는 함수
- 형식 : 오브젝트?string
- 샘플1) <#if item.age?string == “29”>.....</#if>
- 샘플2) ${item.regdate?string(“yyyy/MM/dd HH:mm”)}
- 샘플3) 숫자를 통화표시로 나타내는 예
<#assign MONEY = 1234567>
${MONEY?string(",##0")}

 

11. ?number
- 숫자로 형변환하는 함수
- 형식 : 오브젝트?number
- 샘플1) <#if item.userclass?number &gt; 3>.....</#if>
- 샘플2) ${LIST_POINTS[item.gid?number].entityname?default(“”)}

 

12. ?js_string
- 문자열을 자바스크립트에 유효하도록 필터링해주는 함수. 문자열내에 싱글쿼테이션(‘)등이 포함되어 스크립트에 오류가 나는것을 방지하기 위하여 사용되는 함수이다. 화면상에는 HTML 태그로 취급된다.
- 형식 : 오브젝트?js_string
- 샘플1) 문자열 <img src=’/image/enterprise.gif’>을 js_string으로 처리했을때 소스보기를 하면 <img src=\’/image/enterprise.gif\’>으로 출력된다.
- 샘플2) <a href=”javascript:getName(‘${item.homeurl?js_string}’);”>

 

13. ?html
- 문자열을 HTML Symbolic Entity로 필터링해주는 함수. 문자열내의 HTML태그등을 깨뜨려 화면상으로 출력되도록 할때 사용하는 함수이다. 화면상에 HTML태그가 아닌 일반 문자열로 취급된다.
- 형식 : 오브젝트?html
- 샘플1) 문자열 <img src=’/image/enterprise.gif’>을 html로 처리하면 화면상에 <img src=’/image/enterprise.gif’> 로 출력되고 소스보기를 하면 &lt;img src=’/image/enterprise.gif’&gt;로 출력된다.


14. ?index_of
- 특정 문자(열)가 시작되는 위치를 정수형으로 반환한다. 인덱스는 0부터 시작됨.
- 형식 : 오브젝트?index_of(특정문자)
- 샘플1) “abcde”?index_of(“c”) 는 2를 반환한다.


15. ?replace
- 문자열의 일부를 주어진 문자로 대체하는 함수
- 형식 : 오브젝트?replace(찾을문자열, 대체할문자열)
- 샘플1) ${item.content?replace(“>”, “&gt;”)}

 

16. item_has_next
-리스트 객체의 다음 컨텐츠가 존재하는지(EOF) 체크하는 함수
-형식 : 리스트엘리어스이름_has_next
-샘플1) 이름과 이름사이에 , 를 찍어주되 마지막은 찍지 않는 경우의 예
<#list LIST as item>
${item.name?default(“”)}<#if item_has_next>,</#if>
</#list>

 

by 행복하자 | 2009/05/25 15:52 | JAVA 향기 | 트랙백 | 덧글(2)

java.util.concurrent을 이용한 부하 테스트 환경 구축 예(JAVA SDK 1.5)

/**
 * <PRE>
 * Class/Interface Name : MyThreadPoolTask
 * History
 *     1. 이지홍(hongsgo@gmail.com), 2009. 4. 8., 최초작성
 * </PRE>
 * @brief ThreadPool을 이용한 부하 테스트 예
 * @date 2009. 4. 8.
 * @version 1.0.0
 * @author 이지홍(hongsgo@gmail.com)
 * @warning
 */
public class MyThreadPoolTask implements Runnable {


  private IndexManagerService im = new IndexManagerService();
  private DBIndexJobSaveInfo dbindexjobsaveinfo = null;
  private int type = 0;
  private int pseq =0;

  public MyThreadPoolTask(int type,int pseq) {
   //저장 경로
   im.setRootpath("D:\\workspace_20090325\\temp_index_data");
   //저장객체 식별자
   this.type=type;
   this.pseq=pseq;
  }


  public void run() {
   try {
     if(type==1){
      dbindexjobsaveinfo = new DBIndexJobSaveInfo("pcmong",Integer.toString(pseq+1),DBIndexJobType.DBIndexMakeOne);
     }
     else if(type==2){
      dbindexjobsaveinfo = new DBIndexJobSaveInfo("pcmong",Integer.toString(pseq+1),DBIndexJobType.DBIndexModifyOne);
     }
     else if(type==3){
      dbindexjobsaveinfo = new DBIndexJobSaveInfo("pcmong",Integer.toString(pseq+1),DBIndexJobType.DBIndexDeleteOne);
     }
     //생성된 작업정보 저장 (파일I/O)
     im.setSaveDBIndexJob(dbindexjobsaveinfo);
 } catch (IOException e) {
  System.out.println(e.getMessage());
 }
  }
  public static void main(String[] args) {
    ExecutorService es = Executors.newFixedThreadPool(100); //쓰레드 풀의 갯수 지정
    System.out.println("[임시색인 요청파일 한 폴더에 색인 시작]"); 
    for(int i = 0 ; i < 1000;i++){
     es.execute(new MyThreadPoolTask(1,i));
     es.execute(new MyThreadPoolTask(2,i));
     es.execute(new MyThreadPoolTask(3,i));
    }
    System.out.println("[Finish submitting!]");
    //쓰레드 풀을 릴리즈
    es.shutdown();
  }

}

J2SE 5.0 버전은 병렬 프로그래밍을 위한 라이브러리가 추가되었다.

이것은 JCR(Java Community Process) 의 [JSR166 : Concurrency Utilities] 에 정의되어 있는 내용으로 JSR 166 의 목적은 다음과 같다. (짧은 영어 실력으로 대강 번역해 보았다.)

------------------------------------------------------------------------------------------

  ・간단하고 확장가능한 표준 프레임워크를 제공

    - 자주 사용되는 유틸리티/메소드를 정리해, 쉽게 배울 수 있고, 유지/보수 하기도 편리한 작은

      패키지를 제공

  ・고품질(high-quality) 의 라이브러리(implementations) 를 제공

------------------------------------------------------------------------------------------

 

java.util.concurrent 패키지에는

  ・Thread, synchronized, wait/notify/notifyAll

  ・락(Lock), 상태(Condition), 큐(Queue), 아토믹(Atomic)

과 관련된 클래스, 인터페이스 등이 존재한다.

 

1. Executor

  Executor 는 복수의 태스크를 병렬로 실행시킬 때 쓰이는 프레임워크다. 비동기로 실행시킬

  복수의 처리에 대해, 하나의 처리에 하나의 스레드를 작성하는 것은 리소스를 낭비하는 일이다.

  그 때문에 기존의 스레드를 재사용하는 등의 방법을 생각할 수 있는데, Executor 를 통해 스레드의

  재사용, 타이머(Scheduling) 등의 병렬 처리를 간단히 구현할 수 있다.

------------------------------------------------------------------------------------------

  Executor exe = Executors.newSingleThreadExecutor();

  Runnable run1 = ......

  Runnable run2 = ......

  exe.execute(run1);

  exe.execute(run2);

------------------------------------------------------------------------------------------

  Executors 클래스는 Executor 인터페이스 등을 구현한 인스턴스를 리턴하는 메소드를 제공하는

  클래스이다. Executors.newSingleThreadExecutor() 메소드로 하나의 스레드로 태스크를

  실행시키는 Executor 를 취득, Executor 의 execute() 메소드로 태스크를 실행시킨다.

 

  Executors 클래스에 정의되어 있는 몇 개의 메소드를 살펴보면...

    ◎ newSingleThreadExecutor()

      - 하나의 스레드로 태스크를 처리한다.

    ◎ newFixedThreadPool(int nThreads)

      - 지정한 [nThreads] 수만큼 스레드를 작성, 태스크를 처리한다.

    ◎ newCachedThreadPool()

      - 필요한만큼 자동적으로 스레드를 작성, 태스크를 처리한다.

    ◎ newScheduledThreadPool(int corePoolSize)

      - 지정된 시간에 주기적으로 실행되는 [corePoolSize]만큼의 스레드를 작성, 태스크를 처리한다.

 

2. ExecutorService

  ExecutorService 인터페이스는 Executors 인터페이스에 비해 유용한 기능들이 추가되어 있다.

  (ExecutorService 인터페이스는 Executors 인터페이스를 상속하였다.)

  구체적으로는 스레드의 상태나 태스크 처리를 중지시키는 것이 가능하게 되었다.

 

  ExecutorService 인터페이스에 정의되어 있는 몇 개의 메소드를 살펴보면...

    ◎ submit()

      - 지정된 태스크를 submit, 실행 결과를 Future 형태로 리턴한다.

    ◎ isTerminated()

      - shutdown 된 후, 모든 태스크의 처리가 완료된 경우 true를 리턴한다.

    ◎ shutdown()

      - 스레드를 중지한다. showdown 이전에 submit 된 태스크까지 처리를 완료한다.

    ◎ shutdownNow()

      - 현재 처리중인 태스크의 정지(stop)를 시도(attempt)하고 대기중인 태스크의 처리를 정지(halt)

        한다.

 

  concurrent 패키지에 속한 다수의 인스턴스는 ExecutorService 를 구현(implement) 하고 있다.

 

3. 스레드풀(Thread Pool)

  스레드풀이란 태스크를 큐(Queue)에 추가, 순차적으로 태스크를 처리하는 멀티스레드 형식의 하나

  이다. 필요 이상의 스레드를 작성하지 않기 때문에 리소스를 효율적으로 사용할 수 있다. Executors

  클래스에는 스레드풀에 관련된 몇 개의 메소드가 존재한다.

 

by 행복하자 | 2009/04/08 15:40 | JAVA 향기 | 트랙백 | 덧글(0)

닷넷을 윈도우가 아니어도 사용 할수 있다? - 모노 -

흔히 자바와 닷넷의 차이점을 말하라하면

"어떤 언어든지 괜찮다. 하지만 OS는 윈도우여야만 한다" -->닷넷
"어떤 OS던지 상관없다. 하지만 언어는 자바" -->자바
라고 이야기했었는데
[모노]라는 어플리케이션을 쓰면 리눅스 기반에서도 닷넷을 개발 할 수 있다네요
신기하다능..
근데 아무리 닷넷 프레임워크가 설치되어도 닷넷 프레임워크와 연동하는 다른 환경(NT의 보안메커니즘 과의 연동이라던가 com+와 같은 OS에 종속적인 부분)들이 정말 제대로 동작하는지 의문이 들긴 하네요

by 행복하자 | 2008/12/04 16:38 | 트랙백 | 덧글(2)

DB를 사용하면서 발생 할 수 있는 문제점

웹 이나 윈도우 어플리케이션에 상관없이, 항상 공통적으로 사용되는 부분이 바로 데이터베이스다.
데이터베이스를 사용하겠다는 것은 한마디로 요약하면 "데이터를 저장하겠다"라는 뜻이고,
빈번하게 데이터베이스를 통해 필요한 정보를 갱신하게 되므로, 이에 따른 자원관리는 각별히 신경써야 할 부분이다.
얼마전 구입한 "자바 성능을 결정짓는 코딩 습관과 튜닝이야기(이상민 지음)" 책의 한 챕터를 통해서
데이터베이스 사용과 연관된 문제점들을 살펴 보도록 하겠다.

1. DBConnection과 Connection Pool, DataSource

    1) JDBC관련 API는 클래스가 아니라 인터페이스다.
    2) JDK의 API에 있는 java.sql 인터페이스를 각 DB벤더에서 상황에 맞게 구현하도록 되어있다.

일반적인 방법으로 오라클 DB에 연결하여 사용하는 방법은 다음과 같다.
try{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection con = DriverManager.getConnection("jdbc:oracle:thin:@ServerIP:152:SID","ID","Password");
        PreparedStatement ps = con.prepareStatement("SEELECT .... where id=?");
        ps.setString(1,id);
        ResultSet rs = ps.executeQuery();
        //중간 데이터 처리 부분 생략
} catch(ClassNotFoundException e){
        System.out.println("드라이버 load fail");
        throw e;
} catch(SQLException e){
        System.out.println("Connection fail");
        throw e;
} finally{
    rs.close();
    ps.close();
    con.close();
}

물음 1) 위 소스처럼 JDBC를 사용할때 어느 부분에서 가장 느릴까? 

답: 가장 느린 부분은 Connection 객체를 얻는 부분이다. 왜냐하면 같은 장비에 DB가 구성되어 있다고 하더라도, DB와 WAS 사이에는 통신을 해야하기 때문이다. DB가 다른 장비에 있다면 이 통신 시간은 더 소용된다.


물음 2) DB Connection Pool은 왜 사용해야 하는가?? 

답: Connection 객체를 생성하는 부분에서 발생하는 대기 시간을 줄이고, 네트워크의 부담을 줄이기 위해 사용한다.


물음 3) DataSource와 DB Connection Pool의 차이는 뭘까?

답: DataSourcer는 JDK 1.4 버전부터 생긴 표준이다. Connection Pool로 연결을 관리해야 하고, 트랜잭션 관리도 가능하도록 만들어야 한다.  그러므로 DataSource가 DB Connection Pool을 포함한다고 생각해 두면 된다. 여기서 유의할 점은 DB Connection Pool은 자바 표준으로 지정되어 있는 것이 없다는 점이다. 따라서 WAS 벤더에 따라서 사용법이 많이 상이할 수 있다. 그러나 DataSource는 자바 표준이므로 WAS에 상관없이 사용법이 동일하다.

물음 4) Statement와 PreparedStatement의 차이점은 무엇인가? 성능면에서 무엇이 더 합리적인가?

답:  *참고) CallableStatement는 PL/SQL을 처리하기 때문에 성능상 비교 대상이 없다.
                Statement와 PreparedStatement는 처음 사용할 때에는 다음과 같은 동일한 프로세스를 거친다.
                 1) 쿼리 문장 분석
                 2) 컴파일
                 3) 실행
중요) Statement를 사용하면 매번 쿼리를 수행할 때마다 위의 1~3단게를 거치게 되고, PreparedStatement는 처음 한 번만 이 단계를 거친 후 캐시에 담아서 재사용 한다는 것이다. 만약 동일한 쿼리를 반복적으로 수행한다면, PreparedStatement가 DB에 훨씬 적은 부하를 주며, 성능도 좋다. 또한 쿼리에서의 변수를 ''로 묶어서 처리하지 않고 ? 처리하기 때문에 가독성도 좋아진다.

물음 4) Statement관련 인터페이스를 사용하여 만든 쿼리를 수행할때 여러가지 메소드가 있는데, 그것들간의 차이는 무엇인가?

답: executeQuery(), executeUpdate(), execute() 메소드가 있으며 각각의 사용법 및 특성 및 차이는 다음과 같다.

executeQuery()메소드는 select 관련 쿼리를 수행한다. 수행 결과로 요청한 데이터 값이 ResultSet 객체의 형태로 전달된다. executeUpdate()메소드는 select 관련 쿼리를 제외한 DML(INSERT,UPDATE,DELETE 등 ) 및 DDL(CREATE TABLE,CREATE VIEW)등 쿼리를 수행한다. 결과는 int 형태로 리턴된다. execute() 메소드는 쿼리의 종류와 상관없이 쿼리를 수행한다. eecute() 메소드의 수행결과는 ResultSet이 아닌 boolean 형태의 데이터를 리턴하는데, 만약 데이터가 있을 경우에는 true를 리턴하여 getResultSet() 메소드를 사용하여 결과값을 받을 수 있다. 그렇지 않은 경우에는 false를 리턴하므로 변경된 행의 개수를 확인하기 위해서는 getUpdateCount() 메소드를 사용하여 값을 확인하면 된다.

여기서 한가지 퀴즈. ResultSet 인터페이스를 통해서 1,000건이 되는 데이터를 다음과 같이 받았다.
-------------------------------------------------------------------------
//상단 내용 생략
PreparedStatement ps = con.prepareStatement("SELECT ... where id=?") ; 
ps.setString(1,id);
ResultSet rs = ps.executeQuery();
//하단 내용 생략
그러면 이 ResultSet의 객체 rs에는 몇 건의 데이터가 들어가 있을까?
---------------------------------------------------------------------------
(1) 1건
(2) 10건
(3) 100건
(4) 1,000건
(5) DB마다 다르므로 알 수 없다.
(6) 한 건도 없다.

답은.. 다음 절 끝에서 밝히겠다.

물음 5) JDBC객체를 쓸때 닫아야 하는 것들
일반적으로 JDBC 객체를 얻는 순서는 Connection -> Statement -> ResultSet 순이며, 객체를 닫는 순서는 ResultSet -> Statement -> Connection 순이다. 즉, 먼저 얻은 객체를 가장 마지막에 닫는다.
가장 이상적인 방법은 다음과 같다.(책의 내용을 일부 수정하였고 메소드 단위의 throws 구문이 있다고 가정)

---------------------------------------------------------------------
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try{
    //상단 부분 생략
    con =..;
    ps =..;
    rs =..;
    //중간 생략
} catch(Exception e){
    ...
} finally {
    if(rs != null){
        rs.close();
    }
    if(ps != null){    
        ps.close();
    }
    if( con != null){
        con.close();
    }

}

퀴즈 정답 : "한 건도 없다" 하지만 "DB마다 다르므로 알 수 없다"라고 할 수도 있다. JDK API의 ResultSet 클래스에 대한 설명 중 두 번째 줄에는 다음과 같이 쓰여 있다.

A ResultSet object maintains a cursor pointing to its current row of data.

번역하면 "ResultSet 객체는 현재 열의 데이터를 가리키는 커서를 관리한다"는 말이다. 즉 데이터는 갖고 있지 않고 커서만을 관리하는 객체라는 뜻이다. 하지만 API에 있는 설명은 인터페이스에 대한 설명이므로, 그 인터페이스를 구현한 jdbc를 제공하는 벤더에 따라서 다를 수 있다는 의미가 된다. 일반적으로 10건에서 100건 정도를 미리 갖고 온다. 만약 모든 데이터를 한꺼번에 ResultSet에 담는다고 하자. 10만건의 데이터를 가져오는 쿼리를 수행하면 해당 WAS는 OutOfMemoryError를 발생시키면서 다운 될 것이다.

끝으로 JDBC를 사용하면서 유의할 만한 몇 가지 팁을 이야기 하겠다.

1. setAutoCommit() 메소드는 필요할 때만 사용하자: setAutoCommit() 메소드를 사용하여 자동 커밋 여부를 지정하는 작업은 반드시 필요할 때만 하자. 단순한 select 작업만을 수행할 때에도 커밋 여부를 지정하여 사용하는 경우가 많은데, 여러 개의 쿼리를 동시에 작업할 때 성능에 영향을 주게 되므로 되도록 자제하다.

2. 배치성 작업은 executeBatch() 메소드를 사용하자: 배치성 작업을 할 때에는 Statement 인터페이스에 정의되어 있는 addBatch()메소드를 사용하여 쿼리를 지정하고, executeBatch() 메소드를 사용하여 쿼리를 수행하자. 여러 개의 쿼리를 한번에 수행 할 수 있기 때문에 JDBC 호출 횟수가 감소되어 성능이 좋아진다.

3. setFetchSize() 메소드를 사용하여 데이터를 더 빠르게 가져오자: 한번에 가져오는 열의 개수는 JDBC의 종류에 따라서 다를 것이다. 하지만 가져오는 데이터의 수가 정해져 있을 경우에는 Statement와 ResultSet 인터페이스에 있는 setFetchSize()메소드를 사용하여 원하는 개수를 정의하자. 하지만 너무 많은 건수를 지정하면 서버에 많은 부하가 올 수 있으니, 적절하게 사용해야 한다.

   

    
      
 
        

by 행복하자 | 2008/09/17 16:15 | 트랙백 | 덧글(0)

동기화(synchronized)는 이럴때 사용한다.

동기화 코드의 예
public synchronized void sampleMethod(){
//중간 생략
}
private Object obj=new Object();
public void sampleBlock(){
    synchronized(obj){
       //중간생략
    }
}

    * 동기화를 사용 할 때(synchronized는 생성자의 식별자로는 사용 할 수 없다.)

  • 하나의 객체를 여러 스레드에서 동시에 사용 할 경우
  • 스태틱으로 선언한 객체를 여러 스레드에서 동시에 사용 할 경우
  • static 변수에 동기화를 사용할때는 호출한 메소드도 static이어야 하고, 반드시 필요한 곳에만 사용해야한다,(성능문제)

    * 동기화를 위해서 자바에서 제공하는 JDK 5.0 java.util.concurrent 패키지의 중요한 4가지 개념
        

  • Lock: 실행 중인 스레드를 간단한 방법으로 정지시켰다가 실행시키도록 한다. 상호 참조로 인해 발생하는 데드락을 피할 수 있다.
  • Executors: 스레드를 더 효율적으로 관리 할 수 있는 클래스들을 제공한다. 스레드풀도 제공하므로, 필요에 따라 유용하게 사용 할 수 있다.
  • Concurrent 콜렉션: 앞서 콜렉션 클래스들을 제공한다.
  • Atomic 변수: 동기화가 되어 있는 변수를 제공한다. 이 변수를 사용하면 synchronized 식별자를 메소드에 지정할 필요 없이 사용 할 수 있다.

    더 자세한 사항은 다음의 주소를 참조한다.
    http://java.sun.com/docs/books/tutorial/essential/concurrency/highlevel.html


by 행복하자 | 2008/08/22 01:13 | JAVA 향기 | 트랙백 | 덧글(0)

◀ 이전 페이지          다음 페이지 ▶