item 79 incheol - JAVA-JIKIMI/EFFECTIVE-JAVA3 GitHub Wiki
Effective Java 3e ์์ดํ 79๋ฅผ ์์ฝํ ๋ด์ฉ ์ ๋๋ค.
๊ณผ๋ํ ๋๊ธฐํ
๋ ์ฑ๋ฅ์ ๋จ์ด๋จ๋ฆฌ๊ณ , ๊ต์ฐฉ์ํ
์ ๋น ๋จ๋ฆฌ๊ณ , ์ฌ์ง์ด ์์ธกํ ์ ์๋ ๋์์ ๋ณ๊ธฐ๋ ํ๋ค. ์๋ต ๋ถ๊ฐ
์ ์์ ์คํจ
๋ฅผ ํผํ๋ ค๋ฉด ๋๊ธฐํ ๋ฉ์๋๋ ๋๊ธฐํ ๋ธ๋ก ์์์๋ ์ ์ด๋ฅผ ์ ๋๋ก ํด๋ผ์ด์ธํธ์ ์๋ํ๋ฉด ์ ๋๋ค. ์๋ฅผ ๋ค์ด ๋๊ธฐํ๋ ์์ญ ์์์๋ ์ฌ์ ์ํ ์ ์๋ ๋ฉ์๋
๋ ํธ์ถํ๋ฉด ์ ๋๋ฉฐ, ํด๋ผ์ด์ธํธ๊ฐ ๋๊ฒจ์ค ํจ์ ๊ฐ์ฒด
๋ฅผ ํธ์ถํด์๋ ์ ๋๋ค. (์์ดํ
24) ์ด๋ ์์ธ
๋ฅผ ๋ฐ์ ์ํค๊ฑฐ๋ ๊ต์ฐฉ์ํ
์ ๋น ์ง๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ํผ์ํ ์๋ ์๋ค.
๋ค์์ ์ด๋ค ์งํฉ(Set
)์ ๊ฐ์ผ ๋ํผ ํด๋์ค์ด๊ณ , ์ด ํด๋์ค์ ํด๋ผ์ด์ธํธ๋ ์งํฉ์ ์์๊ฐ ์ถ๊ฐ๋๋ฉด ์๋ฆผ์ ๋ฐ์ ์ ์๋ค.
public class ObservableSet<E> extends ForwardingSet<E> {
public ObservableSet(Set<E> set) {
super(set);
}
private final List<SetObserver<E>> observers = new ArrayList<>();
public void addObserver(SetObserver<E> observer) {
synchronized (observers) {
observers.add(observer);
}
}
public boolean removeObserver(SetObserver<E> observer) {
synchronized (observers) {
return observers.remove(observer);
}
}
private void notifyElementAdded(E element) {
synchronized (observers) {
for(SetObserver<E> observer : observers) {
observer.added(this, element);
}
}
}
@Override
public boolean add(E element) {
boolean added = super.add(element);
if(added) {
notifyElementAdded(element);
}
return added;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean result = false;
for (E element : c) {
result |= add(element); //notifyElementAdded๋ฅผ ํธ์ถ
}
return result;
}
}
๊ด์ฐฐ์๋ค์ addObserver
์ removeObserver
๋ฉ์๋๋ฅผ ํธ์ถํด ๊ตฌ๋
์ ์ ์ฒญํ๊ฑฐ๋ ํด์งํ๋ค. ๋์ผ๋ก ๋ณด๊ธฐ์ ObservableSet
์ ์ ๋์ํ ๊ฒ ๊ฐ๋ค.
๋ค์ ํ๋ก๊ทธ๋จ์ 0๋ถํฐ 99๊น์ง๋ฅผ ์ถ๋ ฅํ๋ค. ํ์์์๋ ์์์ ๊ฐ์ด ์งํฉ์ ์ถ๊ฐ๋ ์ ์ซ๊ฐ์ ์ถ๋ ฅํ๋ค๊ฐ, ๊ทธ ๊ฐ์ด 23
์ด๋ฉด ์๊ธฐ ์์ ์ ์ ๊ฑฐํ๋ ๊ด์ฐฐ์๋ฅผ ์ถ๊ฐํด๋ณด์.
public static void main(String[] args) {
ObservableSet<Integer> set = new ObservableSet<>(New HashSet<>());
set.addObserver(new SetObserver<Integer>() {
public void added(ObservableSet<Integer> s, Integer e) {
System.out.println(e);
if (e == 23) s.removeObserver(this);
}
});
for (int i = 0; i < 100; i++)
set.add(i);
}
์ด ํ๋ก๊ทธ๋จ์ 23๊น์ง ์ถ๋ ฅํ ๋ค์ ConcurrentModificationException
์ ๋์ง๋ค. ๊ด์ฐฐ์์ added
๋ฉ์๋ ํธ์ถ์ด ์ผ์ด๋ ์์ ์ด notifyElementAdded
๊ฐ ๊ด์ฐฐ์๋ค์ ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ ๋์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค. added
๋ฉ์๋๋ ObservableSet
์ removeObserver
๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ , ์ด ๋ฉ์๋๋ ๋ค์ observers.remove
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. ์ฌ๊ธฐ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ๋ฆฌ์คํธ์์ ์์๋ฅผ ์ ๊ฑฐํ๋ ค ํ๋๋ฐ, ๋ง์นจ ์ง๊ธ์ ์ด ๋ฆฌ์คํธ๋ฅผ ์ํํ๋ ๋์ค์ด๋ค. ์ฆ ํ์ฉํ๋ ๋์์ด๋ค.
๊ตฌ๋
ํด์ง ํ๋ ๊ด์ฐฐ์๋ฅผ ์์ฑํ๋๋ฐ removeObserver
๋ฅผ ์ง์ ํธ์ถํ์ง ์๊ณ ์คํ์ ์๋น์ค(ExecutorService
, ์์ดํ
80)๋ฅผ ์ฌ์ฉํด ๋ค๋ฅธ ์ค๋ ๋ํํ
๋ถํํ ๊ฒ์ด๋ค.
set.addObserver(new SetObserver<Integer>() {
public void added(ObservableSet<Integer> s, Integer e) {
System.out.println(e);
if (e == 23) {
ExecutorService exec = Executors.newSingleThreadExecutor();
try {
exec.submit(() -> s.removeObserver(this)).get();
} catch (ExecutionException | InterruptedException ex) {
throw new AssertionError(ex);
} finally {
exec.shutdown();
}
}
}
});
์ด ํ๋ก๊ทธ๋จ์ ์คํํ๋ฉด ์์ธ๋ ๋์ง ์์ง๋ง ๊ต์ฐฉ์ํ
์ ๋น ์ง๋ค. ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๊ฐ s.removeObserver
๋ฅผ ํธ์ถํ๋ฉด ๊ด์ฐฐ์๋ฅผ ์ ๊ทธ๋ ค ์๋ํ์ง๋ง ๋ฝ
์ ์ป์ ์ ์๋ค. ๋ฉ์ธ ์ค๋ ๋
๊ฐ ์ด๋ฏธ ๋ฝ์ ์ฅ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ์ ๋์์ ๋ฉ์ธ ์ค๋ ๋
๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋
๊ฐ ๊ด์ฐฐ์๋ฅผ ์ ๊ฑฐํ๊ธฐ๋ง์ ๊ธฐ๋ค๋ฆฌ๋ ์ค์ด๋ค. ๋ฐ๋ก ๊ต์ฐฉ์ํ๋ค!
์ฌ์ค ๊ด์ฐฐ์๊ฐ ์์ ์ ๊ตฌ๋
ํด์ง
ํ๋ ๋ฐ ๊ตณ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ฅผ ์ด์ฉํ ์ด์ ๊ฐ ์์ผ๋ ์ข ์ต์ง์ค๋ฌ์ด ์์ง๋ง, ์ค์ ์์คํ
์์๋ ๋๊ธฐํ๋ ์์ญ ์์์ ์ธ๊ณ์ธ ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ๊ต์ฐฉ์ํ์ ๋น ์ง๋ ์ฌ๋ก๋ ์์ฃผ ์๋ค.
์ธ๊ณ์ธ ๋ฉ์๋๋ ๋๊ธฐํ๋ ์์ญ ์์์ ์ฌ์ ์ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฑฐ๋ ํด๋ผ์ด์ธํธ๊ฐ ๋๊ฒจ์ค ํจ์ ๊ฐ์ฒด๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋ปํ๋ค
๋คํํ ์ด๋ฐ ๋ฌธ์ ๋ ๋๋ถ๋ถ ์ด๋ ต์ง ์๊ฒ ํด๊ฒฐํ ์ ์๋ค. notifyElementAdded
๋ฉ์๋ ์์ ๊ด์ฐฐ์ ๋ฆฌ์คํธ๋ฅผ ๋ณต์ฌํด ์ฐ๋ฉด ๋ฝ ์์ด๋ ์์ ํ๊ฒ ์ํํ ์ ์๋ค. ์ด ๋ฐฉ์์ ์ ์ฉํ๋ฉด ์์์ ๋ ์์ ์์ ์์ธ ๋ฐ์
๊ณผ ๊ต์ฐฉ์ํ
์ฆ์์ด ์ฌ๋ผ์ง๋ค.
private void notifyElementAdded(E element) {
List<SetObserver<E>> snapshot = null;
synchronized(observers) {
snapshot = new ArrayList<>(observers);
}
for (SetObserver<E> observer : snapshot)
observer.added(this, element);
}
์ฌ์ค ์ธ๋ถ ๋ฉ์๋ ํธ์ถ์ ๋๊ธฐํ ๋ธ๋ก ๋ฐ๊นฅ์ผ๋ก ์ฎ๊ธฐ๋ ๋ ๋์ ๋ฐฉ๋ฒ์ด ์๋ค. ์๋ฐ์ ๋์์ฑ ์ปฌ๋ ์
๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ CopyOnWriteArrayList
๊ฐ ์ ํํ ์ด ๋ชฉ์ ์ผ๋ก ํน๋ณํ ์ค๊ณ๋ ๊ฒ์ด๋ค.
private final List<SetObserver<E>> observers = new CopyOnWriteArrayList<>();
public void addObserver(SetObserver<E> observer) {
observers.add(observer);
}
public boolean removeObserver(SetObserver<E> observer) {
return observers.remove(observer);
}
private void notifyElementAdded(E element) {
for (SetObserver<E> observer : observers)
observer.added(this, element);
}
๋๊ธฐํ ์์ญ
์์์ ํธ์ถ๋๋ค๋ฉด ๊ทธ๋์ ๋ค๋ฅธ ์ค๋ ๋
๋ ๋ณดํธ๋ ์์์ ์ฌ์ฉํ์ง ๋ชปํ๊ณ ๋๊ธฐ ํด์ผ๋ง ํ๋ค. ๊ธฐ๋ณธ ๊ท์น์ ๋๊ธฐํ ์์ญ์์๋ ๊ฐ๋ฅํ ํ ์ผ์ ์ ๊ฒ ํ๋ ๊ฒ์ด๋ค.
์๋ฐ์ ๋๊ธฐํ ๋น์ฉ
์ ๋น ๋ฅด๊ฒ ๋ฎ์์ ธ ์์ง๋ง, ๊ณผ๋ํ ๋๊ธฐํ
๋ฅผ ํผํ๋ ์ผ์ ์คํ๋ ค ๊ณผ๊ฑฐ ์ด๋ ๋๋ณด๋ค ์ค์ํ๋ค. ๊ณผ๋ํ ๋๊ธฐํ๊ฐ ์ด๋ํ๋ ์ง์ง ๋น์ฉ์ ๋ฝ์ ์ป๋ ๋ฐ ๋๋ CPU ์๊ฐ
์ด ์๋๋ค. ๋ฐ๋ก ๊ฒฝ์ ํ๋๋ผ ๋ญ๋นํ๋ ์๊ฐ, ์ฆ ๋ณ๋ ฌ๋ก ์คํํ ๊ธฐํ๋ฅผ ์๊ณ , ๋ชจ๋ ์ฝ์ด๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ผ๊ด๋๊ฒ ๋ณด๊ธฐ ์ํ ์ง์ฐ ์๊ฐ์ด ์ง์ง ๋น์ฉ์ด๋ค.
-
**๋๊ธฐํ
๋ฅผ ์ ํ ํ์ง ๋ง๊ณ , ๊ทธ ํด๋์ค๋ฅผ ๋์์ ์ฌ์ฉํด์ผ ํ๋ ํด๋์ค๊ฐ์ธ๋ถ
์์ ์์์ ๋๊ธฐํํ๊ฒ ํ์** - ๋๊ธฐํ๋ฅผ
๋ด๋ถ
์์ ์ํํด ์ค๋ ๋ ์์ ํ ํด๋์ค๋ก ๋ง๋ค์. (์์ดํ 82)
java.util
์ (์ด์ ๊ตฌ์์ด ๋ Vector
์ HashTable
์ ์ ์ธํ๊ณ ) ์ฒซ ๋ฒ์งธ ๋ฐฉ์์ ์ทจํ๊ณ , java.util.concurrent
๋ ๋ ๋ฒ์งธ ๋ฐฉ์์ ์ทจํ๋ค(์์ดํ
81)
์๋ฐ๋ ์ด์ฐฝ๊ธฐ
์๋ ์ด ์ง์นจ์ ๋ฐ๋ฅด์ง ์์ ํด๋์ค๊ฐ ๋ง์๋ค. ์์ปจ๋ StringBuffer
์ธ์คํด์ค๋ ๊ฑฐ์ ํญ์ ๋จ์ผ ์ค๋ ๋์์ ์ฌ์ฉํ์์๋ ๋ด๋ถ์ ์ผ๋ก ๋๊ธฐํ๋ฅผ ์ํํ๋ค. (๋ค๋ฆ๊ฒ StringBuilder
๊ฐ ๋ฑ์ฅํ ์ด์ ์ด๊ธฐ๋ ํ๋ค)
ํด๋์ค๋ฅผ ๋ด๋ถ์์ ๋๊ธฐํ ํ๊ธฐ๋ก ํ๋ค๋ฉด, ๋ฝ ๋ถํ (lock splitting)
, ๋ฝ ์คํธ๋ผ์ดํ(lock striping)
, ๋น์ฐจ๋จ ๋์์ฑ ์ ์ด(nonblocking concurrecy control)
๋ฑ ๋ค์ํ ๊ธฐ๋ฒ์ ๋์ํด ๋์์ฑ์ ๋์ฌ์ค ์ ์๋ค.
์ฌ๋ฌ ์ค๋ ๋
๊ฐ ํธ์ถํ ๊ฐ๋ฅ์ฑ์ด ์๋ ๋ฉ์๋๊ฐ ์ ์ ํ๋
๋ฅผ ์์ ํ๋ค๋ฉด ๊ทธ ํ๋๋ฅผ ์ฌ์ฉํ๊ธฐ ์ ์ ๋ฐ๋์ ๋๊ธฐํ
ํด์ผ ํ๋ค. ๊ทธ๋ฐ๋ฐ ํด๋ผ์ด์ธํธ๊ฐ ์ฌ๋ฌ ์ค๋ ๋๋ก ๋ณต์
๋ผ ๊ตฌ๋๋๋ ์ํฉ์ด๋ผ๋ฉด ๋ค๋ฅธ ํด๋ผ์ด์ธํธ์์ ์ด ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฑธ ๋ง์ ์ ์์ผ๋ ์ธ๋ถ์์ ๋๊ธฐํํ ๋ฐฉ๋ฒ์ด ์๋ค.
๊ต์ฐฉ์ํ์
๋ฐ์ดํฐ ํผ์
์ ํผํ๋ ค๋ฉด ๋๊ธฐํ ์์ญ ์์์ ์ธ๊ณ์ธ ๋ฉ์๋
๋ฅผ ์ ๋ ํธ์ถํ์ง ๋ง์. ์ผ๋ฐํํด ์ด์ผ๊ธฐํ๋ฉด, ๋๊ธฐํ ์์ญ
์์์์ ์์
์ ์ต์ํ
์ผ๋ก ์ค์ด์. ๊ฐ๋ณ ํด๋์ค
๋ฅผ ์ค๊ณํ ๋๋ ์ค์ค๋ก ๋๊ธฐํ
ํด์ผ ํ ์ง ๊ณ ๋ฏผํ์. ๋ฉํฐ ์ฝ์ด ์ธ์์ธ ์ง๊ธ๋ ๊ณผ๋ํ ๋๊ธฐํ๋ฅผ ํผํ๋ ๊ฒ ๊ณผ๊ฑฐ ์ด๋ ๋๋ณด๋ค ์ค์ํ๋ค. ํฉ๋นํ ์ด์ ๊ฐ ์์ ๋๋ฌธ ๋ด๋ถ์์ ๋๊ธฐํํ๊ณ , ๋๊ธฐํํ๋์ง ์ฌ๋ถ๋ฅผ ๋ฌธ์์ ๋ช
ํํ ๋ฐํ์