반응형
JAVA8에 새롭게 추가된 것을 고르자면 람다를 고를 수 있다. 무조건 람다식을 공부해야 하는것이 아닌 람다의 근간이 되는 함수형 프로그래밍을 공부하여야 한다. JAVA에서 함수형 프로그래밍의 개념을 찾아볼 수 있는것이 바로 람다식이라고 한다.

그럼 함수형프로그래밍이란 무엇인지부터 살펴보자.

1. 함수형 프로그래밍이란?

먼저 이야기 하기 전에 다음과 같은 코드를 보자

take(10, print(number))

take 함수의 두번째 매게변수로 함수가 넘어가고 있다. JAVA에서는 사실 컴파일에러를 내뱉을 것이다. JAVA는 함수를 매개변수로 갖는것이 불가능 했다. 자바의 메소드는 일급 함수가 아니므로, 다른 메소드로 전달할 수 없다. 

일급함수(일급객체)의 특성을 간단히 정리한다면

1. 변수나 데이터 구조안에 담을 수 있다.
2. 파라미터로 전달할 수 있다.
3. 반환값으로 사용할 수 있다.
4. 할당에 사용된 이름과 상관없이 고유한 구별이 가능하다.

람다는 특정 클래스에 종속되지 않고 메서드처럼 파라미터리스트, 바디, 반환 형식등을 포함한다. 
Java8 에서 함수형 인터페이스(단 하나의 메소드만이 선언된 인터페이스)라는 개념을 도입하게 되었고, 함수형 인터페이스의 경우, 람다식으로 표현이 가능할 수 있게 제공하였다.

람다식의 기본적인 문법은 다음과 같다.

(arg1, arg2...) - > {body}
-> 을 기준으로 왼쪽은 파라미터 리스트 오른쪽은 행위이다. 

정리해보자면 아래와 같다.

  • 단순한 람다 구문의 경우, 람다 구분에 중괄호가 없을 수도 있다.

  • return 이 없을 수도 있다.

  • 매개변수에는 타입을 명시하지 않아도 된다. (타입 추론)

  • 람다식 문법을 컴파일러가 익명 클래스로 변환한다. 즉, 함수형 인터페이스를 컴파일러가 구현하도록 위임하는 형태라 볼 수 있다


단순히 문법만 짧아진것이 장점이 아니라 행위를 파라미터로 전달하므로서 더욱 유연하고 재사용 가능한 API를 만들 수 있게 되었다.

이제는 코드를 같이 보면서 람다에 대해 이야기 해보자.


람다 표현식은 구현해야될 추상 메서드가 1개인 인터페이스를 구현한 것이라고 앞서 이야기 하였다. 추후 유지보수를 할때 한개의 메소드를 추가하려하면 람다의 조건은 깨지므로 나머지 코드가 오류가 날것이다. 이를 방지하기 위한 어노테이션이 바로 @FunctionalInterface 이다.

/**
*해당 인터페이스가 함수형인터페이스라는것을 알려주고
*한개 초과의 메서드를 작성할 시 컴파일러 에러를 낸다.
*/
@FunctionalInterface
public interface Movable {
void move(String str);
}


또한, 함수형 프로그래밍에서 함수는 인풋에 의해서만 아웃풋이 달라져야하며 그것을 지원하기위해 람다 표현식으로 구현할때 객체는 상태를 가질 수 없다. 따라서 인스턴스 필드가 들어갈 수 없다.

2. 함수의 파라미터화
앞서 파라미터로 행위를 전달하는것이라고 했다.  자세한 내용을 다음 소스를 통해 알아보자.

public class Fruit {
private String name;
private String color;

Fruit(String name, String color){
this.name = name;
this.color = color;
}

String getName(){
return this.name;
}

String getColor(){
return this.color;
}
}




List<Fruit> extractApple(List<Fruit> fruits){
List<Fruit> resultList = new ArrayList<>();
        for(Fruit fruit : fruits){
            if("apple".equals(fruit.getName())){
             resultList.add(fruit);
        }
    }

         return resultList;
}

    List<Fruit> extractRed(List<Fruit> fruits){
    List<Fruit> resultList = new ArrayList<>();
         for(Fruit fruit : fruits){
            if("red".equals(fruit.getColor())){
             resultList.add(fruit);
        }
    }

    return resultList;
}


소스를 살펴보면 if문 외에는 전부 동일하다. 이걸 행위 파라미터를 이용해 1개의 메서드로 합치면 훨씬 보기가 좋을것 같다.

static List<Fruit> extractFruitList(List<Fruit> fruits, Predicate<Fruit> predicate){
    List<Fruit> resultList = new ArrayList<>();
    for(Fruit fruit : fruits){
        if(predicate.test(fruit)){
            resultList.add(fruit);
        }
    }

 

    return resultList;
}

호출해보자. 
List<Fruit> fruits = Arrays.asList(new Fruit("apple", "red"), new Fruit("melon", "green"), new Fruit("banana", "yellow"));

List<Fruit> appleList = extractFruitList(fruits, new Predicate<Fruit>() {
      @Override
      public boolean test(Fruit fruit) {
          return "apple".equals(fruit.getName());
      }
  });

List<Fruit> redList = extractFruitList(fruits, new Predicate<Fruit>() {
      @Override
      public boolean test(Fruit fruit) {
          return "red".equals(fruit.getColor());
      }
  });

Predicate 인터페이스는 추상메서드가 한개 뿐이므로 람다식 적용가능 하다. 각각에 람다를 적용한다면 다음과 같다.

List<Fruit> appleList = extractFruitList(fruits, fruit-> "apple".equals(fruit.getName()));
List<Fruit> redList = extractFruitList(fruits, fruit-> "red".equals(fruit.getColor()));

https://skyoo2003.github.io/post/2016/11/09/java8-lambda-expression


반응형
반응형
지난번 글에서 RabbitMq의 기본개념에 대해 알아보았다. 추상적으로 밖에 이해가 안가서 다시 여러 글을 읽고 Spring Java를 이용하여 구현하여 보았다.

지난번 포스트에서 추가로 부연된 설명을 하고자 한다.

보통의 웹 어플리케이션이 직접 서버로 연결한 서버-클라이언트 관계라면
메세지 큐를 중간에 위치시킴으로서 라우터 역할을 수행한다.

메세지큐에게 메세지 전송을 모두위임하고 애플리케이션과 서버는 느슨한 관계를 유지할 수 있다.

느슨하게 결합된 시스템 구성의 장점은

1) 발행자 또는 소비자 간 문제 발생 시 서로 영향을 주지 않는다.
2) 각 시스템의 성능은 다른 측면에 영향을 미치지 않는다.
3) 발행자와 소비자의 인스턴스 수는 작업량을 수용할 수 있을 만큼 독립적으로 증가하고 감소한다.
4) 발행자는 소비자의, 소비자는 발행자의 위치가 어디인지 혹은 어떤 기술을 사용하는지 알지 못한다.





AMQP(Advanced Message Queuing Protocol) : 시스템 간 메시지를 교환하기 위해 공개 표준으로 정의한 프로토콜
Broker : 발행자가 만든 메시지를 저장
Virtual host : Broker 내의 가상 영역
Connection : 발생자와 소비자, Broker 사이의 물리적인 연결
Channel : 발행자와 소비자, Broker 사이의 논리적인 연결, 하나의 Connection 내에 다수의 Channel 설정 가능
Exchange : 발행한 모든 메시지가 처음 도달하는 지점으로 메시지가 목적지에 도달할 수 있도록 라우팅 규칙 적용, 라우팅 규칙에는 direct, topic, fanout
Queue : 메시지가 소비되기 전 대기하고 있는 최종 지점으로 Exchange 라우팅 규칙에 의해 단일 메시지가 복사되거나 다수의 큐에 도달할 수 있다
Binding : Exchange 와 Queue 간의 가상 연결

AMQP 모델에는 메세지 확인 개념이 있다. 메세지가 소비자에게 전달되면 Broker에서 알린다. 메세지 확인이 되면 브로커는 큐에서 메세지를 완전히 제거. 

중요한 개념이 Exchange이다. 발행자에게 수신한 메세지를 큐에 적절히 분배하는 라우터 기능을 한다. 각 Exchange와 큐는 가상으로 연결되어있고 이 바인딩 규칙에 따라 큐에 라우팅하는데 그것이 바로 Exchange 타입이다.


지난번 post에서는 조금 어렵게 설명해놓았는데 Exchange type을 다시 설명하려고 한다.

1) Direct Type - 라우팅키와 바인딩키가 완벽하게 일치해야 하는경우 -- 경우에 따라서 멀티 바인딩도 가능하다.




2) Fanout Type - 바운딩되어있는 모든 큐에 메세지를 전송한다. 바인딩, 라우팅키에 상관없이 



3) Topic Type - *와 # 사용 , *는 한개의 단어만 가능 #은 여러개의 단어가 가능
에를들어 rabbit.orange.queue라는 키는 Q1에만 가능 - * 자리에 한개의 단어만 사용하므로
또한 lazy.a.b.c...는 Q2에 가능 - 여러개의 단어가 연이어나와도 #이면 가능하다








즉, Topic type은 *가 오느냐 #가 오느냐에 따라  Fanout Type이 될수도 있고  Direct Type이 될수도 있다.









참조 블로그에 더 자세하게 나와있다.
https://brunch.co.kr/@springboot/6


반응형

'개발공부 > RabbitMq' 카테고리의 다른 글

RabbitMQ 기본 개념, AMQP의 정의  (0) 2018.06.08
반응형

"특정 시간에 특정 작업을 해야한다." 

 


1. 크론탭 기본 (crontab basic)
 crontab -e
-  콜론(:) 입력 후에 wq 를 입력해 크론탭을 갱신
 crontab -l 
- 표준 출력으로 크론탭 내용이 나온다.
 crontab -r
- 크론탭 삭제

2. 주기 결정

 

*      *      *      *      

(0-59)  시간(0-23)  일(1-31)  월(1-12)   2요일(0-7)

 
순서대로 분-시간-일-월-요일 순입니다.

그리고 괄호 안의 숫자 범위 내로 별 대신 입력 할 수 있습니다.

 

3. 주기별 예제

 

1) 매분 실행

 

* * * * * /home/script/test.sh

매분 test.sh 실행 

 

2) 특정 시간 실행

 

45 5 * * 5 /home/script/test.sh 

매주 금요일 오전 5시 45분에 test.sh 를 실행 

 

3) 반복 실행

 


0,20,40 * * * * /home/script/test.sh

매일 매시간 0분, 20분, 40분에 test.sh 를 실행 

 

4) 범위 실행

 

0-30 1 * * * /home/script/test.sh

매일 1시 0분부터 30분까지 매분 tesh.sh 를 실행 

 

5) 간격 실행

 


*/10 * * * * /home/script/test.sh

매 10분마다 test.sh 를 실행 

 

6) 조금 복잡하게 실행

 

*/10 2,3,4 5-6 * * /home/script/test.sh

5일에서 6일까지 2시,3시,4시에 매 10분마다 test.sh 를 실행 

 

주기 입력 방법엔 * , - / 을 이용하는 방법이 있습니다. 위에서 보셨듯이 각각의 특수기호가 하는 기능이 다르고 조합을 어떻게 하느냐에 따라 입맛대로 주기를 설정 할 수 있습니다.

 

4. 크론 사용 팁

 

1) 한 줄에 하나의 명령만 씁시다.

 

잘못된 예)

* * * 5 5

/home/script/test.sh

 잘된 예)

* * * 5 5 /home/script/test.sh

 
2) 주석

 

#############################

# 이것은 주석입니다.                    #

############################# 

 

# 을 입력해서 그 뒤로 나오는 모든 문자를 주석 처리할 수 있습니다.






출처: http://javafactory.tistory.com/119 [FreeLife의 저장소]


반응형

+ Recent posts