DAO, DTO, VO

Development/Java 2012. 3. 16. 18:11

VO

개념

Value Object DTO와 동일한 개념이나 차이 점은 read only 속성을 갖습니다.

Value Object는 관계데이터베이스의 레코드에 대응되는 자바클래스입니다. 형태는 db레코드를 구성하는 필드들을 Value Object Attribute로 하고 해당 변수에 접근 할 수 있는 Getter Setter 메소드의 조합으로 클래스를 형성되어진 클래스입니다. 특성은 대체로 불변성이고 equals()로 비교할 때 객체의 모든 값을 비교해야 합니다.

필요성

Network traffic을 줄임으로 인해서 효과적입니다.

기대효과

Network traffic이 줄어듭니다.

 

장 단점

장점으로는 비 서버 측 클라이언트도 네트워크 오버헤드 없이 영속성 데이터에 액세스 할 수 있다는 점입니다. 데이터 전달을 위해 가장 효율적인 방법이지만, 클래스의 선언을 위해 많은 코드가 필요합니다. 즉 파일수가 많아지게 되고 관리도 힘들어지게 됩니다.

예제 소스코드



DTO

개념

데이터가 포함된 객체를 한 시스템에서 다른 시스템으로 전달하는 작업을 처리하는 객체입니다. Vo dto의 차이점은 vo는 특정한 비즈니스 값을 담는 객체를 vo라 하고 dto는 레이어간의 통신용도로 오가는 객체를 dto라고 합니다.

Vo DTO의 비교

DTO의 나머지 속성은 vo와 똑같다고 생각하여서 차라리 차이점을 비교하려고 합니다.

Core J2EE Patterns 라는 책에서는... Value Object Transfer Object를 동일한 뜻으로 사용합니다만 반대로 Martin Fowler는 저서 Patterns of Enterprise Application Architecture에서 약간 다른 의미로 이야기 합니다. DTO는 메소드 호출 횟수를 줄이기 위해 데이터를 담고 있는 녀석으로, VO는 값이 같으면 동일 오브젝트라고 볼 수 있는 녀석으로 표현을 하고 있습니다.

 

쉽게

DTO a = new DTO(1);

DTO b = new DTO(1);

이라고 했을 때 a != b 이지만,

 

VO a = VO(1);

VO b = VO(1); 이라고 했을때는 a == b라고 정의하는 형태입니다.

사실 이러한 내용도 헷갈리는 부분이 있는게 대부분의 검색에서 사람들은 vo dto를 같은 개념으로 이야기 하고 있어서 아직도 vo dto이런거다라기 보다 거의 똑 같은 개념으로 생각하고 있습니다.

 

DAO

개념

데이터 접근을 목적하는 객체입니다. 커넥션 같은 것을 하나만 두고 여러 사용자가 DAO의 인터페이스를 사용하여 필요한 자료에 접근 하도록 하는 것이 DAO의 개념입니다.

필요성

모든 데이터베이스에 공통적으로 접속 할 수 있는 ODBC가 나왔지만 완벽하진 못했습니다. 여전히 로우 레벨의 API를 포함하고 있었기 때문에 개발 장벽이 여전히 높았습니다. 이런 이유 때문에 개발자들은 정작 데이터베이스에 들어 있는 데이터를 어떻게 이용할지에 초점을 맞추기 보다, 어떻게 데이터베이스에 접속해서 데이터베이스와 교류하는지에 더 초점을 기울였습니다. 즉 데이터를 활용하는 논리적 고민보다 기술적 고민에 더 많은 신경을 썻었습니다. 이런 이유로 DAO란 대안이 나왔습니다.

기대효과

사용자는 자신이 필요한 Interface DAO에게 던지고 DAO는 이 인터페이스를 구현한 객체를 사용자에게 편리하게 사용 할수 있도록 반환해줍니다.

장 단점

DB에 대한 접근을 DAO가 담당하도록 하여 데이터베이스 엑세스를 DAO에서만 하게 되면 다수의 원격호출을 통한 오버헤드를 VO DTO를 통해 줄일수 있고 다수의 DB 호출문제를 해결할 수 있습니다. 또한 단순히 읽기만 하는 연산이므로 트랜잭션 간의 오버헤드를 감소할 수 있습니다.

 그러나 Persistent Storage를 너무 밀접하게 결합해서 작성을 하게 되면 Persistent Stroage를 다시 작성할 경우가 생기는데 이러한 경우 유지 보수의 문제가 생길수도 있습니다.

예제 소스코드

 


출처 -  http://choijaehyuk.com/128 
 





JavaBeans

A JavaBean is a class that follows the JavaBeans conventions as defined by Sun. Wikipedia has a pretty good summary of what JavaBeans are:

JavaBeans are reusable software components for Java that can be manipulated visually in a builder tool. Practically, they are classes written in the Java programming language conforming to a particular convention. They are used to encapsulate many objects into a single object (the bean), so that they can be passed around as a single bean object instead of as multiple individual objects. A JavaBean is a Java Object that is serializable, has a nullary constructor, and allows access to properties using getter and setter methods.

In order to function as a JavaBean class, an object class must obey certain conventions about method naming, construction, and behavior. These conventions make it possible to have tools that can use, reuse, replace, and connect JavaBeans.

The required conventions are:

  • The class must have a public default constructor. This allows easy instantiation within editing and activation frameworks.
  • The class properties must be accessible using get, set, and other methods (so-called accessor methods and mutator methods), following a standard naming convention. This allows easy automated inspection and updating of bean state within frameworks, many of which include custom editors for various types of properties.
  • The class should be serializable. This allows applications and frameworks to reliably save, store, and restore the bean's state in a fashion that is independent of the VM and platform.

Because these requirements are largely expressed as conventions rather than by implementing interfaces, some developers view JavaBeans as Plain Old Java Objects that follow specific naming conventions.

POJO

A Plain Old Java Object or POJO is a term initially introduced to designate a simple lightweight Java object, not implementing any javax.ejb interface, as opposed to heavyweight EJB 2.x (especially Entity Beans, Stateless Session Beans are not that bad IMO). Today, the term is used for any simple object with no extra stuff. Again, Wikipedia does a good job at defining POJO:

POJO is an acronym for Plain Old Java Object. The name is used to emphasize that the object in question is an ordinary Java Object, not a special object, and in particular not an Enterprise JavaBean (especially before EJB 3). The term was coined by Martin Fowler, Rebecca Parsons and Josh MacKenzie in September 2000:

"We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely."

The term continues the pattern of older terms for technologies that do not use fancy new features, such as POTS (Plain Old Telephone Service) in telephony, and PODS (Plain Old Data Structures) that are defined in C++ but use only C language features, and POD (Plain Old Documentation) in Perl.

The term has most likely gained widespread acceptance because of the need for a common and easily understood term that contrasts with complicated object frameworks. A JavaBean is a POJO that is serializable, has a no-argument constructor, and allows access to properties using getter and setter methods. An Enterprise JavaBean is not a single class but an entire component model (again, EJB 3 reduces the complexity of Enterprise JavaBeans).

As designs using POJOs have become more commonly-used, systems have arisen that give POJOs some of the functionality used in frameworks and more choice about which areas of functionality are actually needed. Hibernate and Spring are examples.

Value Object

A Value Object or VO is an object such as java.lang.Integer that hold values (hence value objects). For a more formal definition, I often refer to Martin Fowler's description of Value Object:

In Patterns of Enterprise Application Architecture I described Value Object as a small object such as a Money or date range object. Their key property is that they follow value semantics rather than reference semantics.

You can usually tell them because their notion of equality isn't based on identity, instead two value objects are equal if all their fields are equal. Although all fields are equal, you don't need to compare all fields if a subset is unique - for example currency codes for currency objects are enough to test equality.

A general heuristic is that value objects should be entirely immutable. If you want to change a value object you should replace the object with a new one and not be allowed to update the values of the value object itself - updatable value objects lead to aliasing problems.

Early J2EE literature used the term value object to describe a different notion, what I call a Data Transfer Object. They have since changed their usage and use the term Transfer Object instead.

You can find some more good material on value objects on the wiki and by Dirk Riehle.

Data Transfer Object

Data Transfer Object or DTO is a (anti) pattern introduced with EJB. Instead of performing many remote calls on EJBs, the idea was to encapsulate data in a value object that could be transfered over the network: a Data Transfer Object. Wikipedia has a decent definition of Data Transfer Object:

Data transfer object (DTO), formerly known as value objects or VO, is a design pattern used to transfer data between software application subsystems. DTOs are often used in conjunction with data access objects to retrieve data from a database.

The difference between data transfer objects and business objects or data access objects is that a DTO does not have any behaviour except for storage and retrieval of its own data (accessors and mutators).

In a traditional EJB architecture, DTOs serve dual purposes: first, they work around the problem that entity beans are not serializable; second, they implicitly define an assembly phase where all data to be used by the view is fetched and marshalled into the DTOs before returning control to the presentation tier.


So, for many people, DTOs and VOs are the same thing (but Fowler uses VOs to mean something else as we saw). Most of time, they follow the JavaBeans conventions and are thus JavaBeans too. And all are POJOs.


출처 - http://stackoverflow.com/questions/1612334/difference-between-dto-vo-pojo-javabeans






Enterprise Flex RIA 해부(10) : DTO냐 VO냐?

등록일 : 2008년 08월 25일 | 조회수 : 2,305

전체목록보기
제공 : 한빛 네트워크
저자 : Tony Hillerson
역자 : 이대엽
원문 : Anatomy of an Enterprise Flex RIA Part 10: DTOs or Vos 

지난 기사에서는 애플리케이션에서 엔티티를 영속화하기 위한 액션 스크립트 코드와 자바 코드를 살펴보았다. 이번에는 그러한 엔티티들을 생성, 갱신, 삭제하는 코드가 들어 있는 서비스 계층을 살펴볼 것이다. 

DTO냐 VO냐? 

데이터가 포함된 객체를 한 시스템에서 다른 시스템으로 전달하는 작업을 처리하는 전통적인 엔터프라이즈 패턴은 데이터 전송 객체(DTO; Data Transfer Object, 종종 Value Object나 VO라 불리기도 한다)이다. 간혹 우리가 필요로 하는 것 보다 더 많은 양의 코드가 객체에 필요한 데이터를 데이터베이스에서 가져와 보다 경량 객체인 DTO로 들어간 다음 해당 객체가 필요할 때 전송되는데 사용되기도 한다. 이 경우 EJB 3.0이 데이터베이스에서 데이터를 가져오고 집어넣는 것에 관한 모든 일을 대신 해준다. 엔티티(entity)는 데이터베이스 테이블과의 매핑을 정의하고 전송과 조작을 위해 데이터를 유지할 책임을 이행한다. 

한 가지 알아둘 것은 대부분의 엔터프라이즈 자바 진영에서는 DTO를 표준으로 삼고 있지만 Cairngorm 프로젝트에서는 DTO 대신 대부분 VO를 사용할 것이라는 점이다. 사실 DTO와 VO 모두 같은 것을 의미한다. 

세션 빈 

엔티티 빈(entity bean)과 더불어 세션 빈(session bean)은 서비스를 제공하고 비즈니스 프로세스를 관리하기 위해 EJB 3.0에서 구체화한 클래스의 한 타입이다. 물론 이러한 프로세스의 중심에는 비즈니스 로직에 중요한 엔티티가 자리잡고 있다. 세션 빈은 두 가지 종류로 나뉘는데 상태 유지 세션 빈(stateful session bean)과 상태가 없는 세션 빈(stateless session bean)이 있다. 상태 유지 세션 빈에는 여러 요청(request)에 걸쳐 한 요청에서 다른 요청까지 "대화상태(conversational state)"를 유지하는 세션의 개념이 포함되어 있다. 간단히 말해서 대화상태는 빈의 수명 동안 빈과 상호작용하는 클라이언트에 관한 모든 중요한 정보를 말한다. JBOSS와 같은 EJB 컨테이너는 빈의 이전 클라이언트에서 발생하는 다음 호출에 대해 빈이 대비할 수 있게 한다. 

예제 애플리케이션에서는 대개 다는 아니더라도 RIA에서는 빈이 사용자의 상태를 추적할 필요는 없다. 일반적으로 상태는 RIA를 통해 클라이언트에 유지되는데, 이것은 클라이언트가 메모리상에 머무르면서 단순 웹 페이지처럼 요청-응답 주기에 제약을 받지 않기 때문이다. 그러므로 세션은 상태 유지 세션 빈과 동일하지만 어떠한 상태도 유지하는 않는 상태가 없는 빈을 통해 한 번에 하나의 요청으로 처리될 것이다. 상태 유지 빈은 엔티티에 대해 데이터 접근 객체(DAO, Data Access Object)와 같은 역할을 수행할 것이다. 이는 상태 유지 빈에서 객체를 데이터베이스에 넣고 가져 온다는 것을 의미하며 그런 점에서 상태 유지 빈은 비즈니스 로직을 책임지게 될 것이다. 

아래는 상태가 없는 세션 빈을 생성하는 문법이다:
@Stateless
@Local(value={BookDAO.class})
public class BookDAOBean implements BookDAO {
}
엔티티 빈에 @Entity을 지정하는 것처럼 @Stateless와 대응되는 @Stateful은 클래스를 세션 빈으로 표시한다. 그렇지만 한 가지 또 다른 요구사항은 해당 빈에서 서로 다른 요청에 대해 어느 메소드가 노출되어야 하는지를 컨테이너에 알려주는 인터페이스를 구현하는 것이다. 이러한 요청은 빈은 여러 서버에 걸쳐 배포될 수 있기 때문에 로컬이나 원격에서 수행될 수 있다. 빈은 각기 서로 다른 요청 타입에 어느 메소드를 사용할 수 있는지를 표시하는 하나 이상의 인터페이스를 포함할 수 있다. 우리는 로컬 접근에 대해서만 노출할 필요가 있으므로 어느 클래스의 로컬 인터페이스에 @Local 어노테이션이 지정되어 있는지를 컨테이너에 알려줄 것이다. 아래는 그러한 인터페이스를 보여준다:
package lcds.examples.bookie.dao;
...
public interface BookDAO {
     public void persist(Book transientInstance);
     public void remove(Book persistentInstance);
     public Book merge(Book detachedInstance);
     public Book findById(int id);
     public List getAll();
     public List findByAuthor(Person author);
     public List findBySubject(Subject subject);
     public Collection findByName(String title);
     public void removeDetached(Book detachedInstance);
}
위 코드는 모두 하나의 책이나 책 모음에 대해 수행할 수 있는 것을 나열한 것이다. 아래는 책에 대한 세션 빈을 코드로 작성한 것이다:
package lcds.examples.bookie.dao.beans;

@Stateless
@Local(value={BookDAO.class})
public class BookDAOBean implements BookDAO {
 
     @PersistenceContext
     private EntityManager entityManager;
 
     public void persist(Book transientInstance) {
           try {
                 entityManager.persist(transientInstance);
            } catch (RuntimeException re) {
                 throw re;
            }
      }
 
     public void remove(Book persistentInstance) {
           try {
                 entityManager.remove(persistentInstance);
            } catch (RuntimeException re) {
                 throw re;
            }
      }
위의 두 persist와 remove 메소드는 책 클래스의 인스턴스를 인자로 받아들인다. persist 메소드는 아직 데이터베이스에 존재하지 않는 엔티티에 대해 호출되어야 하며, remove 메소드는 데이터베이스에서 엔티티를 삭제할 것이다. 이 두 메소드는 같은 이름을 가진 EntityManager 타입의 객체에 들어있는 메소드를 호출한다. 그렇지만 주의할 점은 그 객체는 결코 인스턴스화되지 않는다는 것이다. 그 대신 EntityManager에는 @PersistenceContext 어노테이션이 지정되어 있다. 이것은 세션 빈이 EJB 3.0에서 어떻게 처리되는지를 일부 보여준다. EntityManager는 런타임에 인스턴스화되며 컨테이너는 현재 빈이 실행되고 있는 영속화 컨텍스트(persistence context)와 일치하는 EntityManager 인스턴스를 해당 세션 빈에 넘겨준다. 만약 하나 이상의 인스턴스가 존재하면 어노테이션에 원하는 것을 지정할 수도 있지만, 예제에서는 영속화 컨텍스트가 단순히 하나의 영속화 단위이므로 예제의 영속화 단위에 들어있는 빈은 모두 동일한 엔티티 관리자를 획득하게 된다. 

이렇게 컨테이너가 객체에서 필요로 하는 객체의 알맞은 인스턴스를 부여하는 과정을 의존성 주입(dependency injection)이라 한다. 엔티티 관리자는 런타임에 세션 빈에 주입된다. 컨테이너가 적절한 방법으로 엔티티 관리자를 인스턴스화기 때문에 우리는 코드에서 그것을 어떻게 이루어지는 알 필요가 없는데, 이것은 우리가 코드를 작성하는 동안에는 알고 싶지 않은 일들이 있을 수도 있기 때문이다. 이제 몇 가지 메소드를 더 살펴 봄으로써 각 엔티티에 대해 다른 빈에서 수행할 연산의 유형을 확인해 보자:
    public Book merge(Book detachedInstance) {
          try {
                Book result = 
                     entityManager.merge(detachedInstance);
                return result;
           } catch (RuntimeException re) {
                     throw re;
           }
     }

    public void removeDetached(Book detachedInstance) {
          remove(merge(detachedInstance));
     }
persist와 remove 메소드는 기본적으로 SQL의 insert와 delete 문에 매핑된다. merge는 두 가지 경우에 사용될 수 있다. 첫 번째 경우는 직접적으로 SQL의 update문에 해당되는 것인데, merge는 엔티티로부터 변경 내역을 받아들여 데이터베이스를 갱신하기 위해 대기열(queue)에 해당 변경 내역을 추가한다. 그런데 EJB에는 EntityManager에 의해 관리되는 엔티티의 개념이 포함되어 있다. 엔티티 관리자의 remove 메소드가 호출되었을 때 실제로 일어나는 일은 엔티티가 해당 엔티티를 데이터베이스에서 제거하기 위해 대기열에 추가한 관리자에서 제거되는 것이다. 그러나 그 객체는 여전히 존재할 수도 있는데, 코드에서 그 객체를 참조하고 있을 수도 있기 때문이다. 또한 그 객체에 merge를 수행하여 엔티티 관리자로 되돌려 보내는 것도 가능하다. 

이 경우는 준영속(detached) 상태에 있는 엔티티와 엔티티 관리자에 의해 관리되는 엔티티의 차이점을 보여준다. 그럼 준영속 상태에 있는 엔티티에 대해 persist와 merge 메소드를 호출하는 것에는 어떤 차이가 있을까? 사실 아무런 차이가 없다. 두 경우 모두 객체가 존재하지 않는다면 삽입될 것이다. persist 메소드는 엔티티가 이미 데이터베이스 형태로 존재한다면 문제를 겪을 것이나, merge는 그렇지 않을 것이다. 

우리는 종종 데이터베이스에서 개체 관리자로 보내지 않았을 지도 모를 객체를 클라이언트 측에서 보낼 것이므로 만일의 경우에 대비해서 새로운 객체와 기존 객체를 갱신하기 위해 merge 메소드를 상당히 자주 호출할 것이다. 이는 내가 removeDetached 메소드를 작성한 이유를 설명해 주기도 한다. 즉 가끔씩 우리는 미처 엔티티 관리자로 로딩되지 않은 객체를 삭제하고 싶을 수도 있으며, 우리가 그러한 과정을 더 복잡하게 만들지 않는 한 그것을 알지 못할 것이다. 만약 준영속 상태에 있는 엔티티를 제거하려 한다면 엔티티 관리자는 이 객체를 알지 못하므로 오류가 발생될 것이다. 이러한 경우에는 먼저 객체를 merge하여 엔티티 관리자에서 관리하게 한 다음 제거하는 것이 더 쉽다.
    public Book findById(int id) {
          try {
                Book instance = entityManager.find(Book.class, id);
                return instance;
           } catch (RuntimeException re) {
                throw re;
           }
     }
    
    public List getAll() {
          Query q = entityManager.createQuery(
                    "from Book b" +
                    " order by b.title"
               );
               List results = q.getResultList();
               return results;
     }

    public List findByAuthor(Person author) {
          Query q = entityManager.createQuery(
               "from Book b" +
               " where b.author.id = :author_id"
          );
          q.setParameter("author_id", author.getId());
          List results = q.getResultList();
          return results;
     }
필자는 위 코드에 세션 빈을 어떻게 다룰 지에 대한 예제에서 했던 것과 같이 메소드를 몇 개 더 추가하였다. findById 메소드는 개체 관리자의 find(Class, int) 메소드를 호출한다. 이 메소드는 주어진 클래스가 어디에 매핑되는지를 확인한 다음 ID와 일치하는 행을 찾아온다. 간단하다. 

getAll 메소드에서는 질의를 사용하고 있다. 질의는 개체 관리자에서 생성되며, EJB에서는 표준 질의로 SQL 대신 EJBQL을 사용한다. EJBQL은 SQL과 거의 흡사하지만, 여러분은 EJBQL을 이용하여 테이블 대신 클래스를, 컬럼 대신 프로퍼티를 참조할 수 있다. 질의의 결과는 손쉽게 리스트로 변환된다. 

findByAuthor 메소드는 EJB 3.0의 또 다른 질의 기능을 보여준다. SQL와 마찬가지로 EJBQL에도 where 절이 있다. 알아둘 점은 where절의 문법에서 :<매개변수명>의 형식으로 네임드 파라미터(named parameters)를 지정할 수 있다는 것이다. 위 라인에서 우리는 질의를 생성한 다음 setParameter 메소드를 호출하여 저자의 ID를 매개변수로 지정했으므로 질의는 특정한 저자 ID를 가진 책을 모두 찾을 것이다. 

[그림 13]은 데이터 프로젝트의 나머지 세션 빈을 보여준다. 

 
[그림 13] 데이터 프로젝트의 나머지 세션 빈 

다음 연재에서는 TestNG를 이용하여 애플리케이션에서 자바로 작성되어 있는 부분을 테스트하는 것에 관해 살펴볼 것이다. 여기를 클릭하면 전체 시리즈(영문)를 볼 수 있다.


출처 - http://www.hanb.co.kr/network/view.html?bi_id=1554










vo pattern, dao pattern 라고 들어본적은 없구요.

MVC pattern 을 말씀하시는것 같은데요.

이중 사용되는 패턴의 일부중 VO 또는 DAO 를 사용합니다.

MVC 는 가장 기본적으로

JSP 를 사용하신다고 할경우

사용자 화면에 해당하는 JSP

그리고 서버쪽 Servlet

그리고 DataBase 단 DAO 로 나뉩니다.

그리고 JSP <-> Servlet <-> DataBase 등에 데이터를 주고 받는데 있어서

데이터 타입별로 VO 를 사용합니다.

VO 는 가는데마다 이름이 조금씩 다를수 있습니다.

어디서는 DTO 라고 부르기도 하구요.

Value Object 라고 해서 VO 라고 알고 있구요.

DTO 가 Data Template Object 인가 정확하지는 않으니까 찾아보시죠.

DAO 는 DataBase 부분에 쿼리 부분과 쿼리에서 나온 결과값을 VO 에 담아서

리턴하는 식의 작업들을 구현하는것을 말합니다.

VO 는 DB에서 조회하는 데이터가 Name Age 등의 정보가 들어있다고 할경우

VO 내부에 Name 은 String 으로 Age 는 int 형으로 객체를 만들어서 담아서

Servlet 으로 보내고 Servlet 에서는 이를 JSP 로 보내서 사용자에게

보내는 식의 처리를 해주는것이고 이러한 사용 패턴을 세분화해서 말하는것 같습니다.

출처 - 네이버지식







'Development > Java' 카테고리의 다른 글

패키지 이름 정의  (0) 2012.03.18
인터페이스(interface)  (0) 2012.03.18
Thread pool  (0) 2012.03.16
java 어노테이션(Annotation)  (0) 2012.03.14
JVM 인코딩 설정(Dfile.encoding 옵션)  (0) 2012.03.13
Posted by linuxism
,

컬럼 추가
ALTER TABLE <테이블명> ADD <컬럼> <데이터 타입> AFTER <테이브명>



컬럼명 변경, 타입 변경
ALTER TABLE <테이블명> CHANGE <OLD 컬럼> <NEW 컬럼> <데이터 타입>



컬럼 삭제
ALTER TABLE <테이명> DROP <컬럼명>



컬럼 타입 변경
ALTER TABLE <테이블명> MODIFY <컬럼명> <데이터 타입>



테이블명 수정
ALTER TABLE <테이블명>  RENAME <NEW 테이블명>


출처 - http://baljack.tistory.com/9
=========================================================================================

테스트 테이블 생성

DROP TABLE test;
CREATE TABLE test (
   id  INTEGER,
   age  INTEGER,
   name  VARCHAR(50),
   jumin VARCHAR(15),
   PRIMARY KEY(id),
   UNIQUE(age),
   INDEX(name),
   KEY(jumin),
   INDEX(name, jumin)
);

- INDEX를 KEY로 바꿔도 된다.
- INDEX(name, jumin) 과 INDEX(name), INDEX(jumin) 은 다름

- [] 에 들어가 있는 내용은 생략 가능

▶ 테이블 속성 변경
1. 필드 추가
- ATLER TABLE 테이블명 ADD [COLUMN] 추가할필드명 필드타입 [FIRST | AFTER 필드명]
- ATLER TABLE 테이블명 ADD [COLUMN] (추가할필드명 필드타입, ...)

 

2. 필드명 및 타입 변경
- ALTER TABLE 테이블명 CHANGE [COLUMN] 기존필드명 변경할필드명 변경할필드타입 [FIRST | AFTER 필드명]

 

3. 필드 타입 변경
- ALTER TABLE 테이블명 MODIFY [COLUMN] 기존필드명 변경할필드명 [FIRST | AFTER 필드명]

 

4. 필드 삭제
- ATLER TABLE 테이블명 DROP [COLUMN] 제거할필드명

 

5. 필드 디폴트 정의
- ATLER TABLE 테이블명 ATLER [COLUMN] 필드명 {SET DEFAULT 'XXX' | DROP DEFAULT}

 

6. 테이블명 변경
- ATLER TABLE 테이블명 RENAME 변경할테이블명

 

7. COMMENT 추가
- ALTER TABLE 테이블명 COMMENT 'XXX'
-> SHOW TABLE STATUS
- ALTER TABLE 테이블명 MODIFY 필드명 필드타입 [DEFAULT 'XXX'] COMMENT 'YYY';
-> SHOW CREATE TABLE 테이블명

 

▶ 인덱스 관련
1. 인덱스 생성
- CREATE INDEX 인덱스명 ON 테이블명 (필드1, 필드2, ...)
- ALTER TABLE 테이블명 ADD INDEX [인덱스명] [인덱스타입] (필드1, 필드2, ...)
- ALTER TABLE 테이블명 ADD [CONSTRAINT [심볼]] PRIMARY KEY [인덱스타입] (필드1, 필드2, ...)

- ALTER TABLE 테이블명 ADD [CONSTRAINT [심볼]] FOREIGN KEY [인덱스명] (필드1, 필드2, ...) [레퍼런스조건]
- ALTER TABLE 테이블명 ADD [CONSTRAINT [심볼]] UNIQUE [인덱스명] [인덱스타입] (필드1, 필드2, ...)
- ALTER TABLE 테이블명 ADD FULLTEXT [인덱스명] (필드1, 필드2, ...)

 

2. 인덱스 보기
- SHOW INDEX FROM 테이블명

 

3. 인덱스 삭제
- DROP INDEX 인덱스명 ON 테이블명
- ALTER TABLE 테이블명 DROP INDEX 인덱스명
- ALTER TABLE 테이블명 DROP PRIMARY KEY
- ALTER TABLE 테이블명 DROP FOREIGN KEY [fk_symbol]

 

4. 키 활성화
- ALTER TABLE 테이블명 ENABLE KEYS
- ALTER TABLE 테이블명 DISABLE KEYS

 

5. 정렬
- ALTER TABLE 테이블명 ORDER BY 필드명

 

6. 캐릭터 셋
- ALTER TABLE 테이블명 CONVER TO CHARACTER SET 캐릭터셋
- ALTER TABLE 테이블명 CHARACTER SET 캐릭터셋

 

7. 데이터베이트 엔진 변경
- ALTER TABLE 테이블명 ENGINE={InnoDB | MyISAM}

 

▶ 유용 명령어
HELP SHOW
HELP {SELECT | DELETE | UPDATE}
HELP ALTER
HELP ALTER {DATABASE | TABLE}

SHOW PRIVILEGES
SHOW OPEN TABLES
SHOW TABLE STATUS 


출처 -  http://blog.naver.com/goddes4?Redirect=Log&logNo=30116416169 

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

Alter문을 이용하면 테이블에 열을 추가하는 등 구조를 변경할 수 있다.

Alter문에는 여러가지 연산자가 있다. 
 - Add : 테이블에 열을 추가한다.
 - Rename to : 테이블의 이름을 바꾼다.
 - Change : 기존 열의 이름과 데이터 타입을 바꾼다.
 - Modify : 기존 열의 데이터 타입이나 위치를 변경한다.
 - Drop : 테이블의 열을 제거한다.


Add 연산자 
 - 테이블에 열을 추가할 수 있다.

mysql> alter table 테이블명 add column 추가하려는 컬럼명 first(위치);




예) 기존 테이블에 제 1정규화를 적용하려고 한다.(기본키 컬럼 적용)

mysql> alter table 테이블명 add cloumn 컬럼명 int not null auto_increment first,  //첫번재 컬럼위치에 추가
                                       add primary key (컬럼명);                                  // (컬럼명)을 기본키로 설정
                                                                                                            
 
* first는 첫번째 컬럼 위치에 집어 넣으라는 키워드이다. 


* first자리에는 여러 키워드가 들어갈 수 있다.
  - first, second, third, ... , last, before, after 등등


* before과 after 사용방법

mysql> alter table my_contacts add column phone varchar(10) before last_name; 

my_contacts
 contact_id phone  last_name  first_name  email 
 

mysql> alter table my_contacts add cloumn phone varchar(10) after last_name;

 my_contacts
 contact_id last_name phone first_name  email 
  

Alter문의 Rename to 연산자를 이용하여 테이블의 이름을 변경할 수 있다.

mysql> alter table 기존 테이블명 rename to 새로운 테이블명;


Alter문의 Change 연산자를 이용하면 기존 열의 이름과 데이터 타입을 바꿀 수 있다.

mysql> alter table 테이블명 change column 컬럼명 새로운 컬럼명 속성;




예) project_list 테이블의 'number'라는 열의 이름을 'proj_id'로 고친후 제 1정규화를 적용한다.

mysql> alter table project_list change column number proj_id int not null auto_increment,  // 밑줄 : 속성
                                                add primary key (proj_id);          // 기본키 적용


 

한꺼번에 여러개의 컬럼을 수정할 수 있다.

예) project_list 테이블의 컬럼 'descriptionofproj' 를 '
proj_desc' 이름으로 데이터 타입을 varchar(100)으로,
                            컬럼 'contractoronjob'를 'con_name' 이름으로 데이터타입을 varchar(30)으로 수정한다.

mysql> alter table project_list change column descriptionofproj proj_desc varchar(100),
                                          change column contractoronjob con_name varchar(30);

 

 
 * 데이터타입만 수정할 경우 Modify를 활용할 것!
http://warmz.tistory.com/247 
 

예) projekts라는 테이블 이름을 project_list로 바꾸려고 한다. 

myslq> alter table projekts rename to project_list;

Alter문의 Modify 연산자를 이용하면 컬럼의 위치나 데이터 타입을 변경할 수 있다.

mysql> alter table 테이블명 modify column 컬럼명 위치 혹은 데이터 타입




예) 기존의 컬럼명은 그대로 사용하되 데이터 타입을 바꾸려고 한다.

mysql> alter table 테이블명 modify column 컬럼명 varchar(120)

 

열의 순서를 바꾸려면?
 - 테이블이 만들어진 후의 열의 순서를 바꾸는 것은 불가능하다.
 - 한가지 방법은 새로운 열을 원하는 위치에 추가하고 예전 열을 삭제하는 것이다.
 - 또다른 방법은 쿼리 결과 출력시 열이 표시되는 순서를 정해주는 것이다.


* 쿼리 결과 표시되는 열의 순서를 정해주는 방법

mysql> select column3, column1 from 테이블명;
           
            또는
         
            select column1, column3 from 테이블명; 

Alter문에서 Drop 연산자를 이용하면 특정 컬럼을 삭제할 수 있다.

mysql> alter table 테이블명 drop 컬럼명;


* 컬럼을 삭제하면 그 안에 저장되어 있던 모든 데이터는 사라지므로 조심할 것!


출처 - 
http://warmz.tistory.com/248  




Posted by linuxism
,

Thread pool

Development/Java 2012. 3. 16. 10:56

jdk1.5.x 버전부터 
java.util.concurrent 패키지를 제공하고 있다.
패키지 하위에 유용한 클래스들이 많이 존재하므로 
계속해서 살펴보고 익혀야 겠다.

Java5에서  Thread pool을 사용하는 방법이다.
이전 jdk버전에서는 Thread pool을 직접구현해야 했고,
구현을 한다해도, 검증되지 않은 성능 Issue는 항상 개발자를 머리아프게 했었는데...

정말 Good이군~~
    private int threadCount=5;
    private ExecutorService executorService;


    /** thread 숫자를 설정한다. 초기치는 5개 */
    public void setThreadCount(int threadCount) {
        this.threadCount = threadCount;
    }

         - Thread Pool생성

        if (executorService==null) {
            logger.debug("Creating new thread pool for message delivery");
            executorService = Executors.newFixedThreadPool(threadCount);
        }

        - Thread 실행

        /* Spawn a task into the thread pool. */
        executorService.execute(new Runnable(){
            public void run() {
                   //some code that takes some time to run.
            }
        });


       정말 간단하다.
       물론 실제 로직에 적용하기 위해선 부가적으로 추가해야 할것들이 있지만
       우선 jdk기본 패키지에 포함되었다는것은 성능검증은 완료된것이라 봐야 하므로
       의심없이 사용할 수 있을듯 하다.(물론 테스트는 해봐야 한다.)

      만든이가 너무 고맙다!
      

출처 -  http://jace.tistory.com/70 







쓰레드란, 자바에서 유일하게 제공되는 병렬처리용 컨트롤 방식이다. (자바는 프로세스를

fork 할 수 없음)

병렬처리를 위해서 쓰레드를 생성하지만, 쓰레드가 반복적으로 생성, 소멸 과정을 거친다면

단순 쓰레드를 생성하는 방식으로는 리소스를 많이 사용하기 때문에 비 효율적이다. 이때

고려될 방법이 미리 쓰레드를 생성해 놓고, 메모리에서 호출하는 방식인 쓰레드 풀 기법을

사용하면 보다 효율적으로 쓰레드를 사용할 수 있다.

쓰레드풀은 갠적으로 구현해서 사용해도 좋으나, 자바에서 기본적으로 제공하는 검증 된 

쓰레드 풀을 사용하는 것을 추천한다.

 

1. Executor 생성(10개의 풀)

final ExecutorService taskExecutor = Executors.newFixedThreadPool(10);

 

//=====>반복시작

2. 쓰레드로 만들고자 하는 클래스 오브젝트 생성

Runnable myRunnable= new Runnable(){

 public void run(){

MyThread myThread = new MyThread();

}

};

 

3. 쓰레드 실행

taskExecutor.execute(myRunnable);

//=====>반복종료

 

 

4.쓰레드로 생성되는 클래스는 Runnable Interface 를 Implements 하는 방식으로 구현 한다.

public class MyThread implements Runnable {

  public MyThread()

  {

  }

 

  public void run()

  {

  }

}

 

출처 -  http://blog.naver.com/rainbowhand?Redirect=Log&logNo=13012901119 







자바 1.5 버전 부터 쓰래드를 지원하기 위한 API가 강력해진거 같다.

 

모, 일단 라이브러리가 많이 늘어난거 같다. 래치, 배리어, 쓰레드풀 , 퓨처패턴 등등등......

 

나중에 필요할때 써 먹을라고, 관련되는 녀석 공부하던중에

 

자바 1.5부터 지원되는 쓰레드풀 생성하는 아주작은 샘플을 만들어 보았습니당~

 

 

/**
 * 
 */
package test;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 이준성
 *
 */
public class ThreadPoolTest {

 final static int THREADCOUNT = 10;
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  
  
  // 쓰레드 풀 생성. THREADCOUNT 개수 만큼
  ExecutorService exec = Executors.newFixedThreadPool(THREADCOUNT);
  
  for(int i = 0 ; i<THREADCOUNT*2 ; i++) {
   
   exec.execute(new TestThread());
  }
  
  // 쓰레드풀 생성하고 전부다 사용후에는 반드시 셧다운 해야함~
  exec.shutdown();
  

 }
 
 
 
 // 테스트 쓰래드
 public static class TestThread implements Runnable{

  public void run() {
   
   for(int i=1 ; i<= 100 ; i++) {
    
    System.out.println(Thread.currentThread().getName() + " => "+i);
    try {
     Thread.sleep(100);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
     
   }
   
  }  
  
 }

}

 

 

Executors.newFixedThreadPool(THREADCOUNT) 이 부분에 의해서 쓰레드 풀을 생성해서 풀을 넘겨 줍니다.

 

사실 이거말고도 Executors클래스로 생성할수 있는 쓰레드 풀이 3개가 더 존재하더군요.

캐쉬, 싱글익스큐트 등등.

 

Executors.newFixedThreadPool 이 녀석에 의해서 생성되는 쓰레드 풀은 작업이 하나하나 등록할때마다 새로운 쓰레드를 생성한다고 합니다.

 

작업을 등록하는 부분은 exec.execute(new TestThread()) 이 부분 입니다.

 

쓰레드 풀을 사용하지 않을 경우는 Thread를 상속받던가 Runnable을 구현해서 생성하고 스타트 했지만, 쓰레드풀에 작업을 등록하려면 Runnable 이녀석을 구현해서 인자로 넘겨 주기만 하면 됩니다.

 

또 모든 작업이 끝날시에는 셧다운을 해야하는데, 쓰레드 풀 특성을 곰곰히 생각해보시면, 쉽게 아실거라 생각이 듭니다.

쓰레드풀 자체에서 쓰레드 관리(?) 하기 위한 쓰레드가 생성이 되기 때문에, 셧다운을 해주셔야 합니다. 하지않으면~ 프로세스가 남아있더군요.

 

셧다운 하는 방식도 여러가지가 있더군요. 모두 끝낸후에 셧다운 및 강제종료등등

위에서 사용한 방식은 모두 끝낸후에 종료입니다. 아~ 그리고 셧다운후에 작업을 등록하면 익셉션이 발생한다고 합니다.

 

쓰레드풀에서 퓨터 패턴도 적용되어서~ 작업이 끝난 후에 결과값도 받을수 있습니다.

서브밋이라는 메소드를 사용하면 되더군요.

 

시간날때, 다른형태의 쓰레드풀 사용하는 방법과 퓨쳐 패턴 사용방법을 올리지요~


출처 -  http://blog.naver.com/lover4908?Redirect=Log&logNo=110039084541 








* Executor
 * Executor는 굉장히 단순한 인터페이스로 보이지만 아주 다양한 여러 가지 종류의 작업 실행 정책을 지원하는 
 * 유연하면서도 강력한 비동기적 작업 실행 프레임웍의 근간을 이루는 인터페이스다
 
 * Executor는 작업등록(task submission) ,작업실행(task Execution)을 분리하는 표준적인 방법이며,
 * 각 작업은 Runnable의 형태로 정의한다.
 
 * Executor인터페이스를 구현한 클래스는 작업의 라이프 사이클을 관리하는 기능도 갖고 있고,
 * 몇가지 통계값을 뽑아내거나 애플리케이션에서 작업 실행 과정을 관리하고 모니터링하기 위한 기능도 갖고 있다.
 * 
 * Executor의 구조는 프로듀서-컨슈머 패턴에 기반하고 있으며, 작업을 생성해 등록하는 클래스가 
 * 프로듀서(처리해야할 작업을 생성하는 주체)가 되고, 작업을 실제로 실행하는 스레드가 
    컨슈머(생성된 작업을 처리하는 주체)가 되는 모양을 갖추고 있다.

 * 일반적으로 프로듀서-컨슈머 패턴을 애플리케이션에 적용해 구현할 수 있는 가장 쉬는 방법이
   바로 Executor 프레임웍을 사용하는 방법이다.
  1) Executors.newFixedThreadPool(100);  //100개의 스레드
    - 처리할 작업이 등록되면 그에 따라 실제 작업할 스레드를 하나씩 생성한다.
    - 생성할 수 있는 스레드의 최대 개수는 제한되어 있다.
    -  제한된 개수까지 스레드를 생성하고 나면 더이상 생성하지 않고 스레드 수를 유지한다.
  2) Executors.newCachedThreadPool();
    - 캐시 스레드풀은 현재 풀에 갖고 있는 스레드의 수가 처리할 작업의 수보다 많아서 쉬는 스레드가 많이 발생할 때 쉬는 스레드를
        종료시켜 훨씬 유연하게 대응 할 수 있으며, 처리할 작업의 수가 많이 지면 필요한 만큼 스레드를 새로 생성한다.
    - 스레드의 수에 제한을 두지 않는다.
   3) Executors.newSingleThreadExecutor();
  - 단일 스레드로 동작하는 Executor 로서 작업을 처리하는 스레드가 단 하나 뿐이다.
  - 만약 작업중에 Exeception 이 발생해 비정상적으로 종료되면 새로운 스레드를 하나 생성해 나머지 작업을 실행한다.
  - 등록된 작업은 설정된 큐에서 지정하는 순서(FIFO,LIFO,우선순위)에 따라 반드시 순차적으로 처리된다.
   4) Executors.newScheduledThreadPool(100);
  - 일정시간 이후에 실행하거나 주기적으로 작업을 실행할 수 있으며, 스레드의 수가 고정되어 있는 형태의
     Executor.Timer 클래스의 기능과 유사하다.

ExecutorService
  - newFixedThreadPool,newCachedThreadPool 팩토리 메소드는 일반화된 형태로 구현되어 있는  ThreadPoolExecutor
       클래스의 인스턴스를 생성한다.
  - 생성된 ThreadPoolExecutor 인스턴스에 설정값을 조절해 필요한 형태를 갖추고 사용할 수도 있다.
  - Executor 를 구현한 클래스는 대부분 작업을 처리하기 위한 스레드를 생성하도록 되어 있다. 하지만 JVM 은 모든 스레드가 
     종료되기 전에는 종료하지 않고 대기하기 때문에 Executor를 제대로 종료시키지 않으면 JVM 자체가 종료되지 않고
      대기하기도 한다.
  - Executor는 작업을 비동기적으로 실행하기 때문에 앞서 실행시켰던 작업의 상태를 특정시점에 정확히 파악하기가 어렵다.
     어떤작업은 이미 완료되었을 수도 있고, 몇몇 작업은 실행중일 수 있고, 또다른 작업은 큐에서 대기하고 있을 수 있다. 
  - 애플리케이션을 종료하는 과정을 보면 안정한 종료방법과(작업을 새로 등록하지 못하고, 시작된 모든작업이 끝날때 까지 기다림) 
      강제적인 종료 방법이 있겠다. 물론 그사이에 위치하는 여러가지 종료방법이 있겠다.
  - Executor가 애플리케이션에 스레드 풀등의 서비스를 제공한다는 관정으로 생각해 보면 Executor 역시 안전한 방법이든,
      강제적인 방법이든 종료절차를 밟아야할 필요가 있다.
  - 그리고 종료절차를 밟는 동안 실행중이거나,대기중인 작업을 어떻게 처리했는지 애플리케이션에 알려줄 의무가 있다.
  - 이처럼 서비스를 실행하는 동작주기와 관련해 Ececutor를 상속받은 ExecutorService 인터페이스에는 동작주기를 관리할 수 있
    는 여러가지 메소드가 추가되어 있다.
public interface ExecutorService extends Executor{
void shutdown();                                                --> 안전한 종료
List<Runnable> shutdownNow();                         --> 강제종료
boolean isShutdown(); 
boolean isTerminated();
boolean awaitTermination(long timeout,TimeUnit unit) throw InterruptedExeception;
                                                      --> ExecutorService가 종료상태로 들어갈 때까지 기다리고자 할때 사용
..,
}

보통 shutdown() 메소드 실행 후 바로 awaitTermination()을 실행하면 Executor를 직접 종료시키는것과
비슷한 효과를 얻을 수 있다.
ExecutorService exec= Executors.newFixedThreadPool(100);
Callable<V> task = new Callable<V>() {

public V call() throws Exception {
return null;
}
};
Future<V> a = exec.submit(task);
a.get();

 




 * ThreadPoolExecutor :

 * Executors 클래스에 들어있는 newCachedThreadPool, newFixedThreadPool ,newScheduledThreadPool

 * 과 같은 팩토리메소드에서 생성해 주는 Executor에 대한 기본적인 내용이 구현되어 있는 클래스이다.



 * 팩토리메소드를 사용해 만들어진 스레드 풀의 기본 실행 정책이 요구 사항에 잘 맞지 않는다면 ThreadPoolExecutor 클래스의

 * 생성자를 직접 호출해 스레드 풀을 생성할 수 있으며, 생성자에 넘겨주는 값을 통해 스레드 풀의 설정을 마음대로 조절할 수 있다.

 

public ThreadPoolExecutor (int corePoolSize,                  // 스레드풀을 사용할때 원하는 스레드의 개수

int maximumPoolSize,           //동시에 동작할 수 있는 스레드의 최대값

long keepAliveTime,             //스레드의 유지시간

TimeUnit unit,

BlokingQueue<Runable> workQueue,

ThreadFactory threadFactory,

RehectedExecutionHandler handker)

{....}


* newFixedThreadPool의 

*    - 스레드풀의 코어크기,최대크기를 newFixedThreadPool(100) 처럼 파라미터로 지정한 값으로 설정 

*    - 시간제한은 무제한

*    - LinkedBlokingQueue 사용

* newCachedThreadPool

*    - 스레드풀의 최대 크기를 Integer.MAX_VALUE값으로 설정

*    - 코어 크기 :0

*    - 스레드 유지시간은 1분

*    - SynchronousQueue 사용 : 프로듀소에서 생긴 작업을 컨슈머인 스레드에 직접 전달

*       따지고 보면 큐가 아니며, 단지 스레드 간에 작업을 넘겨주는 기능을 담당함

*    - SynchronousQueue에 작업을 추가하려면 컨슈머인 스레드가 이미 작업을 받기위해 대기하고 있어야 하며,

*       대기중인 스레드가 없는 상태에서 스레드의 갯수가 최대 크기보다 작다면 새로운 스레드를 생성시켜 동작한다.

*       최대크기에 다다른 상태라면 작업을 거부하도록 되어 있다.

*    따라서 newCachedThreadPool에서 만들어낸 스레드풀은 크기가 무제한 늘어나며, 

     사용량이 줄어들면 스레드갯수가 적장히 줄어든다


출처 -  http://blog.naver.com/minis24?Redirect=Log&logNo=80152375114 








ExecutorService 를 이용하여 간단하게 ThreadPool를 구현할 수 있다.

 

int poolSize = 10;

//고정 개수의 ThreadPool을 생성한다.(이외 다른 종류는 API를 참고한다.)

ExecutorService e = Executors.newFixedThreadPool(poolSize);

 

//실행을 할때 해당 작업의 완료 여부나 return 값을 알기 위해서는 submit을 이용하고 그외는 execute를 이용한다.

//단순 실행일때

e.execute(Runnalbe);

 

//작업 종료 여부를 알려고 할때

Future f = e.submit(Runnable);

f.isCancelled(); // 작업 종료하기 전 취소 되었는지 여부를 알수 있다 , true - 취소

f.isDone(); //작업이 성공적으로 종료되었으면 true

 

//return 값을 알고 싶을때

Future f = e.submit(Callable);

Object o = f.get(); // 작업이 완료될때까지 기다리며 완료 될때 return 값을 받는다.


출처 -  http://cafe.naver.com/withoracle.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1009& 









Executor 는 어떤 작업을 처리하기 위한 스래드를 생성하는 녀석이다. 이 녀석이 만약 어떤 스래드가 죽어야 하는데 죽지 않고 대기 하는 상황이 생긴다면 JVM 도 죽지 않는다.

즉, 프로그램이 생성되고 메모리 상에서 사라지지 않고 프로그램 생성 시 마다 쌓인다는 것을 의미한다.

Executor 클래스에 내부적인 메소드는 프로그램을 실행하는 메소드만 존재 하고 관련된 스래드를 죽이는 메소드는 존재 하지 않는다고.. 책이 그랬다. ... 그래서 난 의심이 많기 때문에.. 직접 따라가 봤다.

package java.util.concurrent;

public interface Executor
{
    public abstract void execute(Runnable runnable);
}

음... 진짜 그랬다.. ㅡㅡ;

워.. 그럼 Executor 은 실행만 하고... 기타 운영되는 시점에서 자체적으로 운영 최적화 말고는 정말 없는 것인가? 그럼 보통 스래드와 별반 다를게 없다는 것 아닌가..
항상 그러지만 똑똑한 사람들은 먼저 태어났다. 이미 이러한 내용들은 구현이 돼 있다.

바로 ExecutorServiece 란 넘이 이 역할을 하고 있다.
ExecutorServiece 는 Executor을 상속 받아 기본 실행하는 기능을 유지 하면서 안전하게 종료 할 수 있는 기능들을 제공한다.

public interface ExecutorService extends Executor
{
    public abstract void shutdown();

    public abstract List shutdownNow();

    public abstract boolean isShutdown();

    public abstract boolean isTerminated();

    public abstract boolean awaitTermination(long l, TimeUnit timeunit)
        throws InterruptedException;

    public abstract Future submit(Callable callable);

    public abstract Future submit(Runnable runnable, Object obj);

    public abstract Future submit(Runnable runnable);

    public abstract List invokeAll(Collection collection)
        throws InterruptedException;

    public abstract List invokeAll(Collection collection, long l, TimeUnit timeunit)
        throws InterruptedException;

    public abstract Object invokeAny(Collection collection)
        throws InterruptedException, ExecutionException;

    public abstract Object invokeAny(Collection collection, long l, TimeUnit timeunit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

역시 의심이 많은 나는... 역시 따라가봤다.
종료 하는 메소드들이 있다. 거기다가 현재 스래드가 종료 되었는지를 확인하는 메소드도 있었다.

다음은 책에서 손가락으로 복사한 내용이다. 아휴... 힘들어... ㅡㅡ;

내부적으로 ExecutorService 가 갖고 있는 동작 주기에는 running, shutting dowun, terminated의 세가지 상태가 있다. ExecutorService 를 처음 생성 했을때에는 실행 중 상태로 동작한다. 어느 시점엔가 shutdown 메소드를 실행하면 안전한 종료 절차를 진행하며 종료중 상태로 들어간다 . 이 상태에서는 새로운 작업을 등록받지 않으며, 이전 등록되어 있던 작업 까지는 모두 끝마칠 수 있다. shutdownNow 메소드를 실행하면 강제 종료 절차를 진행한다. 현재 진행 중인 작업도 가능한 한 취소시키고, 실행되지 않고 대기 중이던 작업은 더 이상 실행시키지 않는다.
ExecutorService 의 하위 클래스인 ThreadPoolExecutor는 이미 종료 절차가 시작되거나 종료된 이후에 새로운 작업을 등록하려 하면 실행 거절 핸들러를 통해 오류로 처리한다. 실행 거절 핸들러에 따라 다르지만 등록하려 했던 작업을 조용히 무시할 수도 있고, RejectedExecutionException을 발생시켜 오류로 처리 하도록 할 수도 있다. 졸요 절차가 시작된 이후 실행 중이거나 대기 중이던 작업을 모두 끝내고 나면 ExecutorService는 종료 상태로 들어간다. ExecutorService가 종료 상태로 들어갈 때까지 기다리고자 한다면 awaitTermination메소드로 대기할 수도 있고, isTerminated 메소드를 주기적으로 호출해 종료 상태로 들어갔는지 확인할 수도 있고, isTerminated 메소드를 주기적으로 호출해 종료 상태로 들어갔는지 확인할 수도 있다. 일반적으로 shutdown 메소드를 실행한 이후 바로 awaitTermination을 실행하면 마치 ExecutorService를 직접 종료 시키는 것과 비슷한 효과를 얻을 수 있다.

출처 -  http://suein1209.tistory.com/333 

타스크를 실행하기 위해 쓰레드를 생성하는데
만일 실행중인 쓰레드를 중단하고 싶을 때 ExecutorService 를 사용한다.

ExecutorService 는 다음과 같이 세가지 상태가 있다.

- running
- shutting down
- terminated

그리고 다음과 같은 메서드가 존재한다.

shutdown();
shutdownNow();
submit();

shutdown() 은 지금 실행중인 것은 실행할 수 있도록 하지만 
더 이상 새로운 타스크를 받아들이지 않는다.
shutdownNow() 는 지금 실행중인 것을 바로 끝낸다.
리턴 값으로 시작하지 않은 타스크를 돌려주지만
시작했지만 끝내지 않은 타스크의 정보는 알 수 없다.
이것은 프로그램으로 해결할 수 있다.

한가지 주의 할 점은 실제로 작업이 끝났는데도
끝났다고 기록하기 전에 shutdownNow 이 불려지면
타스크가 완료되지 않았다고 할 수 도 있다.

그러나 여러번 실행되어도 상관없는 대부분의 어플리케이션은
이것을 신경 쓸 필요가 없을 것이다.

submit() 는 인수로 넘겨주는 Runnable 이나 Callable 이
실제로 실행되는 쓰레드로 안전하게 넘겨주고
리턴되는 Future 의 get() 이 결과값을 정상적으로
받을 수 있도록 해 준다.


출처 -  http://joejeon.tistory.com/388 

















'Development > Java' 카테고리의 다른 글

인터페이스(interface)  (0) 2012.03.18
DAO, DTO, VO  (2) 2012.03.16
java 어노테이션(Annotation)  (0) 2012.03.14
JVM 인코딩 설정(Dfile.encoding 옵션)  (0) 2012.03.13
자바빈즈(javabeans)  (0) 2012.03.11
Posted by linuxism
,