add
메서드는 스레드 안전 방식으로 channelMessageHolder
CHM을 채우는 다중 스레드에 의해 호출됩니다. 같은 클래스에서 맵을 쓰레드 방식으로 채우고 그 맵을 백그라운드 스레드의 다른 메소드로 전달 하시겠습니까?
channelMessageHolder
에서 데이터를 전달하여
send
메소드를 호출합니다.
public class Processor {
private final ScheduledExecutorService executorService = Executors
.newSingleThreadScheduledExecutor();
private final AtomicReference<ConcurrentHashMap<Channel, ConcurrentLinkedQueue<Message>>> channelMessageHolder =
new AtomicReference<>(new ConcurrentHashMap<Channel, ConcurrentLinkedQueue<Message>>());
private Processor() {
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
send();
}
}, 0, 30, TimeUnit.SECONDS);
}
// this will be called by only single background thread
private void send(ConcurrentHashMap<Channel, ConcurrentLinkedQueue<Message>> messageByChannels) {
for(Entry<Channel, ConcurrentLinkedQueue<Message>> entry : messageByChannels.entrySet()) {
Channel channel = entry.getKey();
ConcurrentLinkedQueue<Message> messageHolder = entry.getValue();
while (!messageHolder.isEmpty()) {
Message message = messageHolder.poll();
....
// process this and send to database
}
}
}
// called by multiple threads
public void add(final Channel channel, final Message message) {
// populate channelMessageHolder in a thread safe way
}
}
질문
는 channelMessageHolder
이미 내 Processor
클래스에 존재 볼 수 있듯이 그래서 명시 적으로 30 초마다이 방법을 보내려면이 맵에서 데이터를 전달해야합니까? 또는 직접 보내기 메서드에서 사용할 수 있습니까?
혼란은 직접 보내기 메서드에서 사용하면 동시에 다중 스레드로 채워집니다. 그래서 send
메서드로 전달하기 위해 AtomicReference의 getAndSet
메서드를 사용하고 있습니다.
내가하는 일이 잘못되었다는 사실을 알려주고 더 좋은 방법이 있습니까?
원자 참조가 필요없는 이유를 설명 할 수 있습니까? 동일한 CHM에서 동일한 데이터를보기 위해 모든 스레드가 필요하다면 그럴 필요가 있다고 생각했습니다. 또한 나는 (업데이트 섹션에서) 사용하고있는 전체 코드로 내 질문을 업데이트했다. 나는 단지 내가 올바른 코드를 얻고 있는지 확인하여 내가 사용할 전체 코드를 확인하려고했다. 병렬로 여러 채널을 실행 중이며 최대 5-6 채널을 갖습니다. 그리고 채널은 내 코드에서 열거 형 클래스입니다. – user1950349
또한 'while true'를 사용하면 영원히 계속 실행됩니다. 그런 경우 30 초마다 실행되는 백그라운드 스레드가 필요하지 않습니까? 내 경우에는 CHM이 언제든지 비어있을 것입니다. 항상 가득 차서 매 30 초마다 실행되지만 무한 루프로 계속 실행되므로 영원히 계속 실행되고 다음 백그라운드 스레드는 실행되지 않습니다. 나는 추측했다. – user1950349
동기화되지 않은 객체를 공유하려고한다면 'AtomicReference'가 @ user1950349 필요합니다. CHM은 이미 내부적으로 동기화되어 있기 때문에 데이터를 직접 동기화 할 필요없이 여러 스레드가 공유 할 수 있습니다. 표준'HashMap'을 사용했다면'AtomicReference'를 사용해야 할 것입니다. – Gray