2017-11-22 6 views
1

A는 상대적으로 자바 8 최근 published article about replacing executors by actors은 익명의 내부 클래스 Runnable를 사용과 같이 밝혔다 작업은 :보다 Runnable 대 방법 참조 및 쓰레기

Actor<String> actor = new Actor<>(parentExecutor, ::onMessage); 

// Equivalent functional operation 
actor.act("Hello world"); 

public void onMessage(String message) { 
    System.out.println(message); 
} 

one should generally use method references over anonymous inner classes (즉 new Runnable, new Callable) 그 의미가 있습니다. 그 아이디어는 잠시 동안 주변에 있었다. 이 액터 패턴을 사용하는 것이 더 효율적이지만이 기사에서 명시 적으로 설명하지 않은 또 다른 미묘한 부분이있는 것처럼 보입니다.

executor.execute(() -> System.out.println(data)); 

분명히 비효율적 일 것 (조금이라도) 컴파일러가 있기 때문에 생성 방법 invokedynamic "호출 사이트"를 생성하고 호출 할 때를 참조 :

내가 사용하는 것으로 알고 있습니다.

의 이점 (1) 직접있어서 기준이 invokedynamic 방법 생성, (2) 수는 별도로이 직접 기준에있어서의 파라미터를 전달할 수있게하는 오버 헤드가 발생하지 않는 것을 여기 있어요? 이 아이디어에서 우리가 이미 알고 사용하고있는 패턴에 대한 핵심 아이디어는 무엇입니까?

+1

첫 번째 연결된 기사가 잘못되었습니다. 더 많은 GC 친숙하지 않다. 각 메소드 참조를위한 객체를 생성해야하기 때문이다. 방금 익명의 클래스 객체를 다른 유형의 객체로 대체했습니다. 메소드 참조 나 람다가 새로운 클래스를 생성하지 않고 두 번째 링크의 포인트이지만 개선 된 GC의 첫 번째 링크에있는 포인트가 잘못 되었기 때문에 클래스가 아니기 때문에 더 나은 클래스입니다. 웹에서 찾은 모든 것을 믿지 마십시오. – Andreas

+0

@ Andreas 내가 말하는 것이 사실이라면 나는 놀랐다. GC 친화적이지 않습니다. 저는 Clebert Suconic - 새로운 ActiveMQ에 관한 기사와 Apache Apache 커미터의 저자 - 그 말을하기 전에 숙제를했을 것입니다. – Dovmo

+0

@Andreas 익명의 클래스가 엔코 드 객체를 캡쳐하는 반면, 람다 또는 메소드 참조는 필요한 부분 만 캡처합니다. 어쩌면 그것이 GC 친화적이라는 의미일까요? – maaartinus

답변

1

이 기사에서는 메서드 참조 대신 람다 식을 사용하는 것이 더 나쁠 것이라고 말하지 않습니다.

의 핵심 아이디어는 대신 Runnable 경우 수백만을 생성, 시간의

executor.execute(new Runnable() { 
    public void run() { 
     System.out.println(data); 
    } 
}); 

수백만 달러를 호출하면

Actor<String> actor = new Actor<>(parentExecutor, this::onMessage); 

한 번 할 및

actor.act(data); 

를 호출이다 수백만 번. Actor은 내부적으로 문자열 (또는 사용하는 데이터 항목)의 대기열을 사용하여 항목을 다른 객체에 래핑하지 않고 ¹ 및 Runnable을 대기열에 추가합니다. 기술적 세부 사항은 관련이없는, 그래서 대신하거나 심지어

Actor<String> actor = new Actor<>(parentExecutor, new ActorListener<String>() { 
    public void onMessage(String message) { 
     System.out.println(message); 
    } 
}); 

Actor<String> actor = new Actor<>(parentExecutor, x -> System.out.println(x)); 

을 할 때 같은이 잘 작동

는 한 번만 실행되는 코드입니다.

람다 식 또는 메서드 참조는이 패턴을 더 쉽게 사용하지만이 패턴의 초석은 아닙니다. 그리고 그 기사는 다르게 말하지 않습니다.그것이 말하는 모든


¹이 하찮은 일에 속 태우고 될 "이 정말 우아한 도착 람다의 사용으로 ", 그것은 시연,는 노드 객체로 각 항목을 포장 않습니다 장면 뒤에 ConcurrentLinkedQueue를 사용 , 어떻게 관련이없는 임시 객체가 될지도 모릅니다. 배열 기반 큐를 사용하면보다 일관성이 있지만 큐가 비 블로킹 일 수는 없습니다. 케이크를 가지고 먹을 수는 없습니다 ...

+0

좋아요, 지금 코드를 다시보고 있다는 말을 듣고 있습니다. 나는 그것을 한 문장으로 요약 할 수있다. 이는 기본적으로 GC 친화적 인 제작자 - 소비자 패턴 구현으로 단일 "액터"를 만들고 그 추상화를 통해 동기화를 관리한다는 통칭적인 설탕을 가지고 있습니다. 나는이 아이디어를 좋아한다. 고맙습니다! 다른 사람들이이 혜택을 누릴 수 있기를 바랍니다. – Dovmo