jdk1.5에서 concurrent library를 사용해서 contention 피하기
Java Concurrency in Practice책에 의하면 jdk1.5의 java.util.concurrent 패키지를 활용하면 동기화에 대한 contention의 부하를 줄일 수 있는 방법들을 제시합니다.
1. ThreadLocal 사용
아래의 예제처럼 ThreadLocal을 통해 synchronization을 대체할 수 있습니다.
initialValue를 오버라이드를 통해 최초에 생성자가 호출 될 경우 해당 변수가 초기화되어 사용이 가능해집니다.
2. ConcurrentMap 사용
java.util.concurrent.ConcurrentHashMap를 사용하여 하나 이상의 쓰레드가 contention하는 것을 보호할 수 있도록 해 줍니다.
3. CopyOnWriteArrayList 사용
Listener (AKA observer) pattern에 사용할 경우 많이 사용됩니다.
1. ThreadLocal 사용
아래의 예제처럼 ThreadLocal을 통해 synchronization을 대체할 수 있습니다.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtil
{
private ThreadLocal<DateFormat> sdf = new ThreadLocal<DateFormat>() {
protected DateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
}
};
public String getCurrentDate()
{
return sdf.get().format(new Date());
}
public static void main(String[] args)
{
DateUtil du = new DateUtil();
System.out.println(du.getCurrentDate());
}
}
initialValue를 오버라이드를 통해 최초에 생성자가 호출 될 경우 해당 변수가 초기화되어 사용이 가능해집니다.
2. ConcurrentMap 사용
java.util.concurrent.ConcurrentHashMap를 사용하여 하나 이상의 쓰레드가 contention하는 것을 보호할 수 있도록 해 줍니다.
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
public class MapUtil
{
private ConcurrentMap<String, String> userMap;
private final int CAPACITY = 100;
private MapUtil()
{
if (userMap == null)
userMap = new ConcurrentHashMap<String, String>(CAPACITY);
}
private void changeUser(String userId, String name)
{
// 동기화 안해도 됨
String lastValue = curMap.put(userId, name);
}
private String findUser(String userId)
{
// 동기화 안해도 됨
return curMap.get(userId);
}
}
3. CopyOnWriteArrayList 사용
Listener (AKA observer) pattern에 사용할 경우 많이 사용됩니다.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ListenerUtil
{
private List<ActionListener> listeners;
public ListenerUtil()
{
listeners = new CopyOnWriteArrayList<ActionListener>();
}
public void addActionListener(ActionListener listener)
{
// 동기화 되지 않음
listeners.add(listener);
}
public void removeActionListener(ActionListener listener)
{
// 동기화 되지 않음
listeners.remove(listener);
}
public void fireActionEvent()
{
for (ActionListener listener : listeners)
{
listener.actionPerformed(new ActionEvent(this, 1, "HELLO"));
}
}
}








