2014. 4. 25. 14:41



출저:  http://iilii.egloos.com/3791596



자바 디자인 패턴 3Factory Method


1. Factory Method패턴은..


factory는 공장이죠. 객체를 막 찍어내는 놈입니다. 객체 선언은 보통 new 객체() 이런식으로 하죠. factory는 내부에서 그런 일을 해줍니다. 즉 factory를 가져다가 쓰는 부분에서는 new 객체()와 같은 식으로 변수를 선언할 필요가 없습니다.Abstract class나 인터페이스에 대해서 다양한 하위 구현체가 있을 경우에 사용하면 좋습니다. 사용법은 Factory.create(인자는 맘대로) 와 같이 됩니다. 


2. 예제


package chap03_StaticFactory;

public interface Animal {

    public void printDescription();

}



package chap03_StaticFactory;

public class AnimalFactory {

    public static Animal create(String animalName){

        if (animalName == null) {

            throw new IllegalArgumentException("null은 안 되지롱~");

        }

        if (animalName.equals("소")) {

            return new Cow();

        }else if (animalName.equals("고양이")) {

            return new Cat();

        }else if (animalName.equals("개")) {

            return new Dog();

        }else{

            return null;

        }

    }

}



package chap03_StaticFactory;

public class Cat implements Animal {

    public void printDescription() {

        System.out.println("쥐잡기 선수");

    }

}



package chap03_StaticFactory;

public class Cow implements Animal {

    public void printDescription() {

        System.out.println("우유 및 고기 제공");

    }

}



package chap03_StaticFactory;

public class Dog implements Animal {

    public void printDescription() {

        System.out.println("주로 집 지킴");

    }

}



package chap03_StaticFactory;

public class Test {

    public static void main(String[] args) {

        Animal a1= AnimalFactory.create("소");

        a1.printDescription();

        Animal a2= AnimalFactory.create("고양이");

        a2.printDescription();

        Animal a3= AnimalFactory.create("개");

        a3.printDescription();

    }

}


이번 것은 소스가 좀 깁니다. 일단 Animal이라는 인터페이스가 있습니다. Cat, Cow, Dog 는 이 인터페이스의 구현체들입니다.

그리고 AnimalFactory가 있는데, 여기서 Animal의 구현체를 돌려줍니다.

Test에서 new Cow()와 같이 하지 않고, AnimalFactory.create("소")를 호출하는 게 일반적인 방법과의 차이입니다.

Animal의 구현체가 더 늘어나면 어떻게 될까요? 전부 new AnotherAnimal()과 같이 생성하는 것보다는 Facotry의 create()메쏘드만 수정하는 게 좀 편하겠죠? 


3. Factory 의 유용성


Animal a1 = AnimalFactory.create("소"); 와 같은 코드에서 a1이 Cow라는 것을 굳이 신경쓰지 않겠다는 겁니다. Test클래스 안에는 new 라는 구문 자체가 없습니다. 정확히 어떤 클래스의 인스턴스인지 신경쓰지 않고 구현할 수 있는 장점이 있습니다. 객체 타입이 굉장히 유연해 질 수 있죠.


4. JAVA API에 있는 Factory Method


Factory 패턴의 중요한 특징 중 하나는 Factory에서 리턴할 때는 매번 객체를 새로 만들지 않을 수도 있다는 겁니다.

Boolean.valueOf(boolean) 을 먼저 살펴 보죠. 

        Boolean a = Boolean.valueOf(true);

        Boolean b = Boolean.valueOf(true);

        System.out.println(a==b);

이 코드를 실행시키면 어떤 결과가 나올까요? true 가 나옵니다. 왜냐하면  Boolean.valueOf(true) 는 Boolean.TRUE 라는 상수를 리턴합니다. 즉, 인스턴스를 새로 만드는 것이 아니라 기존에 있는 것을 그냥 리턴합니다. 매번 새로 만들지 않는다는 거죠. 각종 Wrapper 클래스에 있는 많은 메쏘드 들이 이렇게 구현되어 있습니다.

Calendar.getInstance() 를 호출하면, 사용자 환경에 맞는 Calendar 객체가 리턴됩니다. 보통은 GregorianCalendar가 리턴된죠.

(이 메쏘드의 이름은 좀 잘못지어진 것 같습니다. 보통 getInstance()는 singleton 패턴에서 쓰이는 이름입니다.)


5. Factory Method의 종류


예제에서는 Factory의 인스턴스를 만들지 않고, static 메쏘드인 create()만을 호출했습니다. 이런 방식을 static factory method라고 합니다.

그냥 factory method라고 하면, factory의 인스턴스를 만들어서 쓰는 방식입니다. static factory에 비해 사용 빈도는 좀 떨어지지만, factory의 인스턴스에 귀속되는 객체를 생성해야 할 때는 이런 방식을 씁니다.(static factory에 비해 많이 쓰지 않으므로 자세한 것은 생략합니다.



Posted by hoonihoon
2014. 4. 24. 10:22



빌더 패턴(Builder pattern)이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다. _ wiki


기본 샘플


http://ko.wikipedia.org/wiki/%EB%B9%8C%EB%8D%94_%ED%8C%A8%ED%84%B4



실제 업무상 사용 하는 샘플 


http://www.javacodegeeks.com/2013/01/the-builder-pattern-in-practice.html


http://rdafbn.blogspot.ie/2012/07/step-builder-pattern_28.html


빌더패턴 수정하기


http://jlordiales.wordpress.com/2012/12/24/the-ins-and-outs-of-immutability/




Android builder pattern 샘플

https://github.com/nostra13/Android-Universal-Image-Loader/blob/master/sample/src/com/nostra13/example/universalimageloader/UILApplication.java

https://github.com/nostra13/Android-Universal-Image-Loader/blob/master/library/src/com/nostra13/universalimageloader/core/ImageLoaderConfiguration.java

Posted by hoonihoon
2014. 1. 2. 23:48

Vector와 ArrayList 의 공통점

순서가 있는 Collection 이다.

데이터를 중복해서 포함할 수 있다.

List 인터페이스를 구현하고 있다.


Vector와 ArrayList 의 차이점 동기화 여부 차이 입니다.

Vector  : 자동으로 동기화를 보장 해준다.  (안전성이 좋다)

ArrayList : 멀티스레드를 이용할때 동기화를 보장해주지 않는다.  (Vector 보다 속도 빠름)


ArrayList 동기화 지원 방법

List list = Collection.synchronizedList(new ArrayList());

동기,비동기 관련 포스트 보러 가기 click click !



도움되는 글 

-질문-

채팅 서버 만들고 있는데...(동접 1000명 정도 생각중) 

vector를 쓰는게 나은가요 아니면 arraylist 동기화해서 쓰는게 나은가요?

vector가 옛날꺼지만 동기화때문에 쓰려고 하는데..(채팅서버 특성상 멀티스레드 돌리거든요)

속도도 느리고 여러모로 구형이라......

arraylist동기화 하려니 만약 동기화해서 속도가 느려지면 그밥에 그나물 이라는 생각도 들고...

아니면 vector시대에 비해 컴속도도 빨라졌고 자바도 발전했으니 

그냥 arraylist동기화 하는게 여러모로 더나은지..

그것도 아님 동기화시에 유리한 다른 벡터계열의 함수가 있는지요..

java는 1.5버전으로 하고 있습니다.

 

 

-답변-

어차피 Vector 나 ArrayList나 Serializable(직렬 선형구조(인덱스를 참조하는..))한 자료형이므로

색인 속도는 비슷하지 않을까 싶어요..

그리고 일정 수준이상 하드웨어면은 개미털만큼에 속도차이밖에 안날듯 싶네요..

더군다다 1000명정도 동접할 채팅서버면 따로 서버장비를 둘 필요없을 정도로 소규모니까

리소스때문에 뻣거나 할일은 거~~의 없을듯 싶습니다..

(네트워크가 받쳐주고 프로그램을 재대로 짰다고 가정하에...)

 

프로그램 즉 코딩하는 측면에 생각해 보면 List가 Vector 보단 쓰기 편하겠지요

Vector는 초기화에 사이즈를 주어야 하기 때문에 첨부터 메모리에 maximum 사이즈를

올려야 하고 만약 최대사이즈 이상일 경우에 동작하는 Exception 처리도 따라오겠네요..

List는 동적할당이므로 최대사이즈 없이 노드를 생성하여 붙이니까 클라이언트가

붙는만큼 메모리에 적재시킬 수 있으니까 자원관리측면에서 이득이지 않을까 싶네요

또한 노드를 릴리즈 시키면 자동으로 메모리 반환도 가능하구요

 

 

서버를 어떻게 구성할지는 모르겠지만 Request/Response 를 어떻게 구성할지도 생각해 봐야겠네요 

동기식으로 할지 비동기식으로 할지....

동기 비동기에 따라서 서버구성도 다르게 구성되야겠고 Thread를 최대 몇개까지 어떻게

쓸껀지도 속도에 큰 요인이 되겠네요..

아무래도 Thread를 많이 붙이면 클라이언트와 거의 동기식 처리가 가능하겠지만

그만큼 자원할당이나 메모리관리 등이 복잡해질 우려가 있으니 잘 고민하시기 바랍니다.

비동기식이면 단순하게 스케쥴 관리를 위한 큐와 Send-Reciver 쓰레드로도 구성할 수 있겠네요..


Posted by hoonihoon
2013. 12. 23. 19:41

시스템 프로퍼티란 시스템 환경에 관한 정보를 말한다.

System 클래스에 있는 getProperty() 메서드를 이용하면,
현재 사용하고 있는 환경 정보를 얻을 수 있다.
System 클래스를 이용하기 위해서는 java.util 패키지를 임포트 한다.


import java.util.*;
.
.
String version = System.getProperty("java.version");

 

주요 프로퍼티는 아래와 같다.
프로퍼티 : 의미 : 표시 예
java.version : Java 의 버전 : 1.4.2_13
java.vendor : Java 의 벤더(공급자) : Sun Microsystems Inc.
java.vendor.url : Java 의 벤더의 URL : http://java.sun.com
java.home : Java 를 인스톨한 디렉토리 : c:\j2sdk1.4.2_13
java.class.version : Java 클래스의 버전 : 48
java.class.path : Java 클래스가 존재하는 경로 : c:\Java
java.ext.dir : 확장기능 클래스를 포함하는 디렉토리 : null (미설정의 경우)
os.name : OS 의 이름 : Windows XP
os.arch : OS 의 아키텍처 : x86
os.version : OS 의 버전 : 5.1
file.separator : 파일을 구분하는 문자 : \(Unix 에서는 /)
path.separator : 경로를 구분하는 문자 : (Unix 에서는 :)
line.separator : 행을 구분하는 문자(개행코드) : \n
user.name : 사용자 계정 : Na
user.home : 사용자 홈 디렉토리 : c:\Document and Settings\Na
user.dir : 현재 작업 디렉토리 : c:\Java


이를 구현하기 위해 직접 코딩을 해보았다.

<a.java 의 내용>-------------------------
import java.util.*;

class a{
  public static void main(String args[]){
    System.out.println("java.version : " + System.getProperty("java.version"));
    System.out.println("java.vendor : " + System.getProperty("java.vendor"));
    System.out.println("java.vendor.url : " + System.getProperty("java.vendor.url"));
    System.out.println("java.home : " + System.getProperty("java.home"));
    System.out.println("java.class.version : " + System.getProperty("java.class.version"));
    System.out.println("java.class.path : " + System.getProperty("java.class.path"));
    System.out.println("java.ext.dir : " + System.getProperty("java.ext.dir"));
    System.out.println("os.name : " + System.getProperty("os.name"));
    System.out.println("os.arch : " + System.getProperty("os.arch"));
    System.out.println("os.version : " + System.getProperty("os.version"));
    System.out.println("file.separator : " + System.getProperty("file.separator"));
    System.out.println("path.separator : " + System.getProperty("path.separator"));
    System.out.println("line.separator : " + System.getProperty("line.separator"));
    System.out.println("user.name : " + System.getProperty("user.name"));
    System.out.println("user.home : " + System.getProperty("user.home"));
    System.out.println("user.dir : " + System.getProperty("user.dir"));
  }
}
----------------------------------------

만약, 출력결과를 텍스트 파일로 보고 싶다면,

>java a > 1.txt

라고 실행하면, 실행결과를 1.txt 파일로 출력해준다.



첨부파일: system_getProperty.zip


Posted by hoonihoon
2013. 12. 20. 16:52

Servlet 를 이용한 파일 업로드를 간단하게 완성 시켰습니다.

사진과 글이 <Form> 태그를 통해 온 것을 파싱 할 수 있는 MultipartRequest 를 사용했습니다.


1. cos.jar 를 다운 받아 주세요.

 http://www.servlets.com/cos/ 접속해서 받거나 아래 아이콘을 클릭해서 받으면 된다.

cos.jar


2. 파일업로드 서블릿을 생성하고 web.xml파일에 Servlet를 추가해주세요.


public class UploadServlet extends HttpServlet{

public UploadServlet() {

super();

}

public void init() throws ServletException {}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {

FileManager fileManager = new FileManager(req); 

        }


3. FileManager class 를 만들어서 File을 관리할 수 있도록 했습니다.

MultipartRequest Class를 이용하면 File 복사가 되고, 파일명을 바꾸고 싶으면 마지막 파라미터를 주의 깊게 보시면 됩니다.


public class FileManager {

private MultipartRequest mRequest;

private int postMaxSize = 10 * 1024 * 1024;   //10MB

      private String encoding = "UTF-8";

public FileManager(final HttpServletRequest req) throws IOException {

mRequest = new MultipartRequest(req, 이미지저장 Path, postMaxSize, encoding, new FileAlteration());

}

}



4. 마지막 파라미터에 FileAlteration 이라는 class를 inner class 로 생성 했습니다.


class FileAlteration implements FileRenamePolicy {

@Override 

public File rename(File file) {

String parentDir = file.getParent();

String fileName = file.getName();

//Get the extension if the file has one

       String fileExt = "";

       int i = -1;

       if(( i = fileName.indexOf(".")) != -1){

           fileExt = fileName.substring(i);

           fileName = fileName.substring(0,i);

       }

       //Add the timestamp and user ID

       String userId = (String) req.getSession().getAttribute("id");

       newFileName = /*fileName + "_"+ */userId +("_"+( new Date( ).getTime( ) / 1000)) + fileExt;

      

       //piece together the filename

       newFileFullName = parentDir + 

        System.getProperty("file.separator") + newFileName;

       

       file = new File(newFileFullName);

       mimeType = new MimetypesFileTypeMap().getContentType(file);


return file;

}

}



위 소스를 보시면 쉽게 이해하실 수 있을거 같습니다.

파일작성자의 아이디와 TimeStamp 값을 이용해서 새롭게 생성될 파일의 이름을 만들어 주면 됩니다.

아래와 같이 파일이 저장됩니다.




단순한 업로드가 완성 되었습니다.


지금 하고 있는 모바일웹프로젝트에 글과+사진이 함께 전송하도록 하기 위해 한 것입니다.

파일업로드 뿐만 아니라 

게시판테이블에 글 정보 삽입, 방금 삽입된 레코드의 INDEX 를 가져오는 루틴,

파일정보를 담은 테이블에 정보 삽입, 게시판 테이블 UPDATE 까지 고려해야 합니다.





Posted by hoonihoon
2013. 12. 19. 23:17

Java 자바 4대 중첩클래스 (instance class, static class, local class, anonymous class)

 

1. 일반 중첩클래스

 

중첩클래스는 효율적인 관리를 위한 하나의 형식이다. 프로그램에서는 하나의 대표 클래스 내에 다른 클래스들을 넣어 관리할 수 있는 형식을 제공한다. 그것은 대표 클래스가 그들 모두에 있어 공통적인 속성 값만 가지고 나머지는 각기 다른 중첩 클래스에서 관리하도록 만드는 것이다. 즉, 중첩클래스란 하나의 클래스 내부에 또 다른 클래스를 사용할 수 있는 것이다. 당연히 중첩되는 클래스는 하나 이상일 수 있다.

 

그렇다면 클래스 외부에서 중첩클래스 내부의 멤버들에는 어떻게 접근할까? 우선 바깥쪾에 있는 클래슬 Outer

클래스라 하고 안쪽에 있는 클래슬 Inner클래스라 하자. 

 

■ 중첩클래스 접근 형식

Outer 객체1 = new Outer();  <=Outer클래스 객체 생성 방법

Outer.Inner 객체 2 = 객체 1.new Inner(); <=Inner클래스 객체 생성 방법

 

간단한 코딩을 통해 내부 멤버에 접근해 보자.

 

 

 

 

여기서 중첩 클래스에는 각각 Outter클래스에 x의 멤버를 Inner클래스에는 y의 멤버를 배치해 두었다. 각 데이터를 사용하는 방법은 x는 Outter클래스 멤버이기 때문에 Outer클래스의 객체를 발생시키고, y는 Inner클래스 멤버이기 때문에 Inner클래스 객체를 발생시켜 접근하면 된다.

 

또한 Inner클래스에서는 Outer클래스의 멤버를 이용할 수 있다. 아래 코딩을 보면 객체 생성없이 바로 Inner클래스에서 Outter클래스의 멤버를 이용할수 있음을 알 수 있다.

 

 

 

 

 하지만 Outer클래스에서는 Inner클래스의 멤버를 사용할 수 없다.

사용하고 싶다면 객체를 직접 발생시켜야 한다 . 다음 코딩을 보면 Outer클래스 Inner클래스를 사용하기

위해서 객체를 발생시키는걸 알 수 있다.

 

 

 

 

 

 

 

2. 정적 중첩 클래스

 

다음으로 살펴볼 것은 중첩 클래스 내부에서 static과 관련된 멤버를 선안할 수 있는 클래스이다.

이것은 단순히 클래스 이름 앞에 static이라는 예약어만 붙이면 되고, 이런 클래스를 정적(static)

중첩 클래스라고 한다.

 

class Outer{

     static class Inner{

...........

}

}

 

정적 중첩클래스는 static의 특성상 객체를 독립적으로 만들 수 있다.

 

■ 정적 중첩클래스의 객체 생성 방법

Outer.Inner  객체 = new Outer.Inner();

 

일반 중첩 클래스와 달리 Outer클래스의 객체가 없어도 Inner클래스의 객체를 만들 수 있다. 또한 static멤버를

선언할 수 있고, static메서드도 만들어 사용할 수 있다. 그래서 반드시 Inner클래스에 static을 선언하여 사용하고

싶다면 정적 중첩클래스를 사용해야 한다. 또한 객체의 선언 방식은 일반 중첩클래스의 객체 선언 방식을 사용할 수 없고 위와 같이 Outer.Inner 객체 = newr Outer.Inner(); 로만 객체를 발생시킬 수 있다. 문제는 Outer클래스의 멤버를 끌어다 쓰는 것이 문제인데, 끌어다 쓰려는 Outer클래스의 멤버가 static인 경우에만 사용할 수 있다.

 

그렇다면 만인 main()메서드를 Inner클래스에 사용하고 싶다면 어떻게 해야 할까? 먼저 main()메서드는 그 자체가 static이기 때문에 정적 중첩 클래스를 사용해야 한다.

 

 

 

 

3. 지역 중첩 클래스

 

일반적으로 클래스라는 것은 재상용을 염두해 두고 만들어진 것인데 이런 클래스가 특정 메서드를 실행할 때에만 필요하고 별로 사용할 경우가 없다면 그것을 굳이 외부에 드러나는 형태로 만들 필요는 없을 것이다. 그래서 특정 메서드에 한정적인 용도로 사용할 클래스로 지역 중첩 클래스라는 개념이 등장하였다. 그러나 이 경우는 접근 제한자와 지정 예약어를 사용할 수 없는 형태이다.

 

 

 

위의 코딩을 보면 main()메서드 안에 Inner클래스가 들어가 있는 상황이다. 여기서 만일 일반 중첩 클래스처럼 main()메서드의 멤버인 x를 사용하려면 그 멤버는 반드시 final로 선언되어 있어야 한다.

 

 

4. 익명 중첩 클래스

 

익명 중첩 클래슨느 지역 중첩 클래스의 변형된 형태라고 할 수 있다. 이것은 이름에서 알 수 있듯이 class라는 예약어와 클래스명을 가지지 않고 단지 instance의 생성과 내용부의 정의만 가진다. 한가지 주의할 점은 여기에 사용되는 중첩 클래스는 이미 기존에 존재하는 것이어야 한다. 또한 이 내부에서 사용할 수 있는 외부 멤버도 역시 final로 선언되어 있어야 한다.

 

 


출저: http://kwy1052.tistory.com/41?viewbar

Posted by hoonihoon
2013. 12. 19. 11:07


blocking 모드 

어떤 시스템 콜을 호출하였을 때 네트워크 시스템이 동작을 완료할 때까지 그 시스템 콜에서 프로세스가 멈춤

소켓 생성시 디폴트 blocking 모드

listen(),connect(), accept(), recv(), send(), read(), write(), recvfrom(), sendto(), close()

block 될 수 있는 소켓 시스템 콜

I/O시 처리가 될 때까지 기다려야 함. 비 동기적인 작업 수행 불가능

일 대 일 통신을 하거나 프로그램이 한가지 작업만 하면 되는 경우는 blocking 모드로 프로그램을 작성할 수 가능


Non-blocking 모드

소켓 관련 시스템 콜에 대하여 네트워크 시스템이 즉시 처리할 수 없는 경우라도 시스템 콜이 바로 리턴되어 응용 프로그램이 block되지 않게 하는 소켓 모드

통신 상대가 여럿이거나 여러 가지 작업을 병행하려면 nonblocking 또는 비동기 모드를 사용하여야 한다.

non-blocking 모드를 사용하는 경우에는 일반적으로 어떤 시스템 콜이 성공적으로 실행될 때까지 계속 루프를 돌면서 확인하는 방법(폴링)을 사용한다.




정리 .....


동기 : 순서 있게 일한다. 


비동기: 신호를 보내고, 받는다. (무순서)


Blocking

- 리턴값에 신뢰성이 있다. 대신에 기다려야 한다.

- 어떤 시스템 콜을 호출 하였을 때 네트워크 시스템이 동작을 완료 할 때까지 시스템 콜에서 프로세스가 멈춤.


Non_Blocking 

- 네트워크가 즉시 처리 할 수 있으면 해당 결과를 리턴  ( 바로 리턴하는 대신 신뢰성을 보장하지 못함)

- 리턴값을 대게 -1, false 를 리턴한다.

- 결과 확인은 위한 반복적인 작업(폴링)으로 CPU 낭비를 초래한다.





<노컷님 정리>


* 더 쉬운 예(프린터를 예로 들어서, 문서 10개를 print시킬때)
1. sync : 문서를 작성하고 print시킨다. 다 프린트 되서 나올때까지 기다려서 확인.
          그 다음 문서를 print시키고, 다 나올때까지 확인.(당연 절라 느림)
          (거기다 사람(application)이 계속 기달리고 있어야 함...시간 아깝죠?^^)
2. async : 문서를 print시키라고 마구 시킨다.(프린터야 죽어나든 말든..)
           글구 사람(application)은 코딩작업을 마무리 하던가, 데브피아에 답변을
           올리던가...일을 하다가 printer가 일이 끝나면, 삐~~(신호음)을 울려주고
           그때서야 프린트가 잘 됐나 한번 봐준다^^
          (사람(application)을 부릴땐 이렇게 시켜야 효율적으로 일하겠죠?^^)
          (실제로 쓰이고 있는 방식입니다.)
3. non-blocking방식 : 프린트 시키고 딴짓하다가 프린트가 나오기 시작하면,
          다 끝날때까지 기다림(sync보단 효율적이고, async보단 더 느리고)
          (recv함수를 쓰는 동안은 기다리니깐요)

동기는 프로그래밍하기가 좋고, 비동기는 좀 더 까다로운 대신 기능이 좋죠^^

덧. async가 네트워크 속도가 빠른 건 아닙니다(확인하고 보내는 시간이 없으니 조금 
더 빠르긴 하지만...프린트를 1000장을 시킬때, 완료될때까지 걸리는 시간은 그렇게 
차이가 안나죠, 문제는 사람(application)이 하루종일 기달리고 있느냐, 하루종일 딴
일하고, 마지막에 확인만 해주느냐의 차이인 것이죠.^^


출저:




아래 읽어보세요.

Non Blocking IO 에 관한 질문..

litdream의 아바타

어제, 후배가 'Non blocking IO 를 왜 쓰나요?' 라고 물어오더군요.
솔직히 한번도 non-blocking IO 를 써본적이 없는 저로써는,
잘 모르겠다만, 내가 알기로는 머 이러이러하다라고 말해준것이
계속 맘에 걸립니다. 잘못 얘기해준것 같아서요.

" 어떤 function call 이 blocking socket 에 대해 이루어질때,
버퍼가 비어있다면 버퍼에 무엇인가 들어올때까지 프로세스는 sleep
상태가 되고, OS 는 다른 프로세스를 선택하게되지만,
non-blocking socket 에 대해 이루어지면, 버퍼가 비어있으면,
펑션은 바로 NULL 을 리턴하게되고, 곧바로 다음 문장을 실행하게
된다. 이것이 가지는 장점은, (여기서 잠시 머뭇하다가.. )
select() 나 poll() 같은 펑션에 소켓을 등록한후, 그 몽땅을 하나의
channel 로 관리하게 되므로, 각각의 소켓에 쓰레드를 할당하는것
과 대조적으로 하나의 쓰레드로 관리할수 있게되므로, 쓰레드에서
잇점이 있다. "

막상 이렇게 정리를 해놓고 보니 넘겨짚은 부분이 많은것 같아서요.
그리고, 설명을 못해준것이, 
1. 이것이 performance 입장에서는 어떻게 더 나은지..
2. 이것이 scalable 한 이유.

이런 문제에 관해서는 전혀 생각을 못했네요.
고견을 부탁드립니다.

kane의 아바타

제가 알고 있는 장점은thread context switching을

제가 알고 있는 장점은
thread context switching을 줄일 수 있다는 겁니다.
프로세스 보다야 낫겠지만 쓰레드도 컨텍스트 스위칭에 오버 헤드가 있기 때문에 이걸 줄일 수 있다면 좋습니다. 특히 소켓 수가 많고, 소켓 통신이 빈번하게 이루어지는 상황이라면 이 오버 헤드도 무시 못할 게 되죠.
대신에 코딩하기 귀찮아진다는 (무시 못할 ㅋㅋ) 단점이 있지만요.

추가로 소켓을 쓰레드에 분배하거나, 쓰레드끼리 데이타를 주고 받을 필요가 발생해서 생기는 오버 헤드도 있을 수 있습니다.

aqwerf의 아바타

select나 poll을 사용하였을 때의 장점은 performance나

select나 poll을 사용하였을 때의 장점은 performance나 scale면에서는 큰 장점은 없는 것 같습니다.

하지만, 
- thread를 여러개 만드는 것보다는 select를 사용하는 것이 메모리 사용면에서 효율 적이고
- 다른 io event와 같이 기다릴 수 있다
는 장점이 있을 것 같습니다.

저 같은 경우에는 두번째의 용도로 많이 씁니다. 예를 들어 소켓 통신 중 중단 시키려는 경우 빨리 깔끔하게 뒷처리를 하도록 하기 위해서는 blocking인 경우 thread를 바로 깨워줘야 하는데 이를 위한 방법이 없어서요. 
제가 주로 사용하는 것이 RTOS인데 unix는 이런 경우에 깨울수 있는 방법이 있나요?

ssehoony의 아바타

throughput 과 response time 간 trade off 관

throughput 과 response time 간 trade off 관계인데요.
일단 이거 단일 프로세스라는 가정에서 이야기를 하면

throughput 은 select 가 좋습니다.
kane 님께서 말씀 하셨듯이 컨텍스트 스위칭, 쓰레드 스케줄링, 크리티컬섹션의 뮤텍스 처리등이 쓰레드를 이용하면 생기는 부하들인데 이런 것들이 없기때문에 전체 성능은 좋아집니다.

하지만 select 는 (쓰레드와 비교해 상대적으로) response time 이 떨어집니다. 클라이언트 입장에서는 다른 클라이언트가 서버에 먼저 뭔가 요구했다면 그 작업이 끝날때까지 기다렸다가 내 차례가 오기때문이죠.

위와 같은 상황은 커널이 프로세스 스케줄링할때 어떤 알고리즘을 사용하느냐 그리고 한 프로세스에 한번에 주는 cpu 시간의 크기에 따라 throughput 과 response time 이 trade off 관계인것 과 같은 것이지요.

또한 쓰레드를 쓰면 각각의 쓰레드 생성 오버헤드도 있고 각 쓰레드의 스택세그먼트 공간을 생각하면 메모리 낭비가 문제지요.

그럼 쓰레드는 뭐가 좋냐? 위에 말씀 드린 것 처럼 response time 이 짧고 (클라이언트 입장에서 보면 서버의 throughput 은 자기완 전혀 상관없고, response time 이 중요하죠), 크리티컬섹션을 제외한다면 코드도 select 보다 간단하고, 멀티 프로세서일때 필요하다면 모든 프로세서를 동시에 병렬로 이용해서 단일 프로세서의 select 보다 더 좋은 throughput 을 낼 수도 있습니다.

litdream의 아바타

Context Switch 의 Overhead 가 있었군요!!이런이런

Context Switch 의 Overhead 가 있었군요!!
이런이런~ 가장 기본적인것을 놓치다니.. 역시 내공이 부족합니다.
답변주신 세분 감사합니다.

삽질의 대마왕...

pynoos의 아바타

NonBlock IO를 쓰는 가장 큰 이유는 소켓의 데이터 처리에 대한

NonBlock IO를 쓰는 가장 큰 이유는 소켓의 데이터 처리에 대한 스케쥴링을 OS나 일반적인 라이브러리에 맡기지 않고, 스스로 구현한 스케쥴링을 사용하겠다는 것입니다.

그리고, OS의 다른 overhead인 process/thread의 스케쥴링 비용(요것이 소켓 100개정도만 넘어가도 상당한 비용이 됩니다.)을 없애겠다는 것입니다.

윗분들이 언급하지 않은 것 하나는 select 또한 소켓수가 100개 이상되면 비용이 작은 것이 아닙니다. select는 각 소켓의 버퍼에 WATER MARK 이상의 값이 있는지에 대해 반응하는 것입니다. 대개 WATER MARK 값은 1로 설정되어 있고, 그 값보다 크게 데이터들이 들어와 있는지를 일일이 비교합니다. 즉 data의 level에 따라 select되는 것이고, 매번 I/O로부터 데이터가 올라왔을 때 바로 반응하는 epoll 을 사용하는 것이 좋습니다.

---
coolengineer.com


Posted by hoonihoon
2013. 12. 19. 11:03
동기 비동기 차이  (Synchronous, asynchronous 차이)

상대방의 일정 신호에 의해서 다음 동작이 이루어 지면 동기식
상대방의 상태와 관계없이 일방적으로 동작하면 비동기식


아래와 같은 함수가 있다면 getList() 메소드가 끝나면 list(Print)를 실행해야 되므로 동기식으로 되어야 한다.
getList();
listPrint();


ajax 에서 

1234567891011121314151617
// 전화번호를 검색하여 받아온다.
var telNo = '';
$.ajax({
url : '',
data : {},
type : 'post',
sendDataType : 'json',
success : function(data) {
telNo = data;
}
});
 
// 전화번호를 넣어준다.
$('#telNo').val(telNo);
 
// 정상적으로 전화번호를 넣어주지 못한다.
// success function에 console.log(data)를 찍어보면 잘나온다.

비동기로 처리 되기 때문에 흐름상으로 보면 ajax가 처리되고 난다음 telNo를 넣어줄꺼라

생각되지만, 실제 처리 되는 순서를 보면 ajax를 호출을 하고 data를 받지 못한상태에서

telNo에 값을 넣어주게 된다.

이는 ajax의 async option default값이 true로 되어 있기 때문이다.

그래서 ajax async option을 false로 주어야지만 정상적인 처리가 된다.

123456789101112131415
// 전화번호를 검색하여 받아온다.
var telNo = '';
$.ajax({
url : '',
data : {},
type : 'post',
sendDataType : 'json',
async : false,
success : function(data) {
telNo = data;
}
});
// 전화번호를 넣어준다.
$('#telNo').val(telNo);



Posted by hoonihoon