Coding Planet
[์ดํํฐ๋ธ ์๋ฐ]chapter2 : [์์ดํ 7] ๋ค ์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํด์ ํ๋ผ ๋ณธ๋ฌธ
๐ป Java Study/Java ์ด๋ก ์ ๋ฆฌ
[์ดํํฐ๋ธ ์๋ฐ]chapter2 : [์์ดํ 7] ๋ค ์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํด์ ํ๋ผ
jhj.sharon 2023. 8. 19. 20:40๋ฐ์ํ
์์ดํ 7 : ๋ค ์ด ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ํด์ ํ๋ผ
C, C++ ์ธ์ด๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๊ด๋ฆฌํ์ง๋ง ์๋ฐ์ ๊ฒฝ์ฐ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ด ์ญํ ์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ค ์ด ๊ฐ์ฒด๋ ์์์ ํ์๋๋ค. ํ์ง๋ง ์ด ๊ฒ์ด ๋ฉ๋ก๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ ๊ฒฝ์ฐ์ง ์์๋๋๋ค๋ ์๋ฏธ๋ ์๋๋ค.
1. ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์ผ์ด๋๋ ์์น๋ ์ด๋์ธ๊ฐ?
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
return elements[--size];
}
private void ensureCapacity() {
if (elements.length == size) {
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
}
- ์ ์ฝ๋์์๋ ์คํ์ด ์ปค์ก๋ค๊ฐ ์ค์ด๋ค์์ ๋ ์คํ์์ ๊บผ๋ด์ง ๊ฐ์ฒด๋ค์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ํ์ํ์ง ์๋๋ค.
- ์คํ์ด ๊ทธ ๊ฐ์ฒด๋ค์ ๋ค ์ด ์ฐธ์กฐ(obsolete reference)๋ฅผ ์ฌ์ ํ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค. ๋ค ์ด ์ฐธ์กฐ๋ ๋ฌธ์ ๊ทธ๋๋ก ์์ผ๋ก ๋ค์ ์ฐ์ง ์์ ์ฐธ์กฐ๋ฅผ ๋ปํ๋ค.
- ์ฝ๋์์๋ elements ๋ฐฐ์ด์ 'ํ์ฑ ์์ญ'๋ฐ์ ์ฐธ์กฐ๋ค์ด ๋ชจ๋ ์ฌ๊ธฐ์ ํด๋นํ๋ค. ํ์ฑ ์์ญ์ ์ธ๋ฑ์ค๊ฐ size๋ณด๋ค ์์ ์์๋ค๋ก ๊ตฌ์ฑ๋๋ค.
- ๊ฐ์ฒด ํ์ฐธ์กฐ ํ๋๋ฅผ ์ด๋ ค๋๋ฉด ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ ๊ทธ ๊ฐ์ฒด ๋ฟ ์๋๋ผ ๊ทธ ๊ฐ์ฒด๊ฐ ์ฐธ์กฐํ๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ํ์ํ์ง ๋ชปํ๋ค. ์ด๋ก ์ธํด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ์ผ์ด๋๊ฒ ๋๋ค.
ํ์ฑ์์ญ(Active Region) - ํ์ฑ์์ญ์ 'elememts' ๋ฐฐ์ด์์ ํ์ฌ ์ฌ์ฉ ์ค์ธ, ์ฆ ์คํ์ ์ค์ ๋ก ์ ์ฅ๋ ์์๋ฅผ ์๋ฏธํ๋ค. - ์คํ์์ 'size'๋ณ์๋ ์คํ์ ํ์ฌ ํฌ๊ธฐ, ์ฆ ์ ์ฅ๋ ์์์ ์๋ฅผ ์๋ฏธํ๋ค. ๋ฐ๋ผ์ 'elements'๋ฐฐ์ด์์ ์ธ๋ฑ์ค๊ฐ 0๋ถํฐ 'size-1'๊น์ง์ ์์๋ค์ด ํ์ฑ ์์ญ์ด๋ค. ๋ค ์ด ์ฐธ์กฐ (Obsolete Reference) - ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๊ฐ ๋ ์ด์ ํ์ํ์ง ์์ง๋ง, ์ฐธ์กฐ๊ฐ ์ฌ์ ํ ์กด์ฌํ๊ณ ์์ด ๊ฐ๋น์ง ์ปฌ๋ญํฐ๊ฐ ํด๋น ๊ฐ์ฒด๋ฅผ ํ์ํ์ง ๋ชปํ๋ ์ํฉ์ ์๋ฏธํ๋ค. - 'pop' ๋ฉ์๋์์ ์์๋ฅผ ์คํ์์ ์ ๊ฑฐํ ๋, ์ค์ ๋ก๋ ํด๋น ์์์ ์ฐธ์กฐ๋ฅผ 'elements' ๋ฐฐ์ด์์ ์ ๊ฑฐํ์ง ์๋๋ค. ๋์ 'size' ๋ณ์๋ง ๊ฐ์์์ผ 'ํ์ฑ ์์ญ'์ ์ค์ธ๋ค. ์ด๋ก์ธํด 'size'๋ณด๋ค ํฐ ์ธ๋ฑ์ค์ ์๋ ์์๋ค์ "๋ค ์ด ์ฐธ์กฐ"๊ฐ ๋๋ฉฐ, ์ด ์ฐธ์กฐ๋ค ๋๋ฌธ์ ํด๋น ๊ฐ์ฒด๋ค์ด ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ํ์๋์ง ์๊ฒ ๋๋ค. |
2. ๋ฉ๋ชจ๋ฆฌ ๋์ ํด๊ฒฐ๋ฐฉ๋ฒ
- ํด๋น ์ฐธ์กฐ๋ฅผ ๋ค ์ผ์ ๋ null ์ฒ๋ฆฌ(์ฐธ์กฐ ํด์ )ํ๋ฉด ๋๋ค. ์ ๋๋ก ๊ตฌํ๋ pop ๋ฉ์๋๋ ์๋์ ๊ฐ๋ค.
public class Stack {
// ...
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null; // ๋ค ์ด ์ฐธ์กฐ ํด์
return result;
}
}
- ์์ฒ๋ผ ๋ค ์ด ์ฐธ์กฐ๋ฅผ null๋ก ์ฒ๋ฆฌํ๋ฉด null ์ฒ๋ฆฌํ ์ฐธ์กฐ๋ฅผ ์ค์๋ก ์ฌ์ฉํ๋ ค ํ๋ฉด ํ๋ก๊ทธ๋จ์ ์ฆ์ NullPointerException์ ๋์ง๋ฉฐ ์ข ๋ฃ๋๋ฏ๋ก ํ๋ก๊ทธ๋จ ์ค๋ฅ๋ฅผ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ ์ ์๋ค.
- ๊ทธ๋ฌ๋ ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ null ์ฒ๋ฆฌํ๋ ์ผ์ ์์ธ์ ์ธ ๊ฒฝ์ฐ์ฌ์ผ ํ๋ค. ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ค ์ฐ์๋ง์ ์ผ์ผ์ด null ์ฒ๋ฆฌํ๋ ๊ฒ์ ํ๋ก๊ทธ๋จ์ ํ์ ์ด์์ผ๋ก ์ง์ ๋ถํ๊ฒ ๋ง๋ค ๋ฟ์ด๋ค.
- ๋ค ์ด ์ฐธ์กฐ๋ฅผ ํด์ ํ๋ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ ๊ทธ ์ฐธ์กฐ๋ฅผ ๋ด์ ๋ณ์๋ฅผ ์ ํจ ๋ฒ์(scope) ๋ฐ์ผ๋ก ๋ฐ์ด๋ด๋ ๊ฒ์ด๋ค. ๋ณ์์ ๋ฒ์๋ฅผ ์ต์๊ฐ ๋๊ฒ ์ ์ํ์.
- ์๋์ฒ๋ผ ์์ ํ๋ฉด, result ๋ณ์๋ pop ๋ฉ์๋์ ์ง์ญ ๋ณ์์ด๋ฏ๋ก ํด๋น ๋ฉ์๋๊ฐ ์ข ๋ฃ๋ ๋ ์๋์ผ๋ก ๋ฒ์(scope)๋ฅผ ๋ฒ์ด๋๊ฒ ๋๋ค. ๋ฐ๋ผ์ result์ ์ ์ฅ๋ ๊ฐ์ฒด ์ฐธ์กฐ๋ ๋ฉ์๋๊ฐ ์ข ๋ฃ๋๋ฉด ์๋์ผ๋ก ํด์ ๋๋ค.
public Object pop() {
if (size == 0) {
throw new EmptyStackException();
}
// ์ง์ญ ๋ณ์๋ก ๊ฐ์ฒด ์ฐธ์กฐ ๊ฐ์ ธ์ค๊ธฐ
Object result = elements[size - 1];
// ์ฐธ์กฐ๋ฅผ ํด์
elements[size - 1] = null;
size--;
// ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
return result;
}
| ๊ทธ๋ ๋ค๋ฉด null ์ฒ๋ฆฌ๋ ์ธ์ ํด์ผํ ๊น??
- ์ผ๋ฐ์ ์ผ๋ก ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ง์ ๊ด๋ฆฌํ๋ ํด๋์ค๋ผ๋ฉด ํญ์ ๋ฉ๋ชจ๋ฆฌ ๋์์ ์ฃผ์ํด์ผ ํ๋ค. ์์๋ฅผ ๋ค ์ฌ์ฉํ ์ฆ์ ๊ทธ ์์๊ฐ ์ฐธ์กฐํ ๊ฐ์ฒด๋ค์ ๋ค null ์ฒ๋ฆฌํด์ค์ผ ํ๋ค. stack ํด๋์ค ๋ํ ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ elements ๋ฐฐ์ด๋ก ์ ์ฅ์ ํ์ ๋ง๋ค์ด ์ง์ ๊ด๋ฆฌํ๋ฏ๋ก ๋์์ ์ทจ์ฝํ ์ ๋ฐ์ ๋ฒ๋ค.
- ๊ทธ๋ฌ๋ฏ๋ก ํ๋ก๊ทธ๋๋จธ๋ ๋นํ์ฑ ์์ญ์ด ๋๋ ์๊ฐ null์ฒ๋ฆฌํด์ ํด๋น ๊ฐ์ฒด๋ฅผ ๋๋ ์ฐ์ง ์์ ๊ฒ์์ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์๋ ค์ผํ๋ค.
3. ์บ์์์์ ๋ฉ๋ชจ๋ฆฌ ๋์
- ์บ์ ์ญ์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํค๋ ์ฃผ๋ฒ์ด๋ค. ๊ฐ์ฒด ์ฐธ์กฐ๋ฅผ ์บ์์ ๋ฃ์ด๋๊ณ ์ด ์ฌ์ค์ ๊น๋งฃ๊ฒ ์์ ์ฑ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ค์ด ๋ค๋ก๋ ํ์ฐธ ๊ทธ๋ฅ ๋๋ ์ ๋ ์๋ค.
- ์บ์ ์ธ๋ถ์์ ํค(key)๋ฅผ ์ฐธ์กฐํ๋ ๋์๋ง(๊ฐ์ด ์๋๋ค) ์ํธ๋ฆฌ๊ฐ ์ด์ ์๋ ์บ์๊ฐ ํ์ํ ์ํฉ์ด๋ผ๋ฉด WeakHashMap์ ์ฌ์ฉํด ์บ์๋ฅผ ๋ง๋ค์.
- ๋ค ์ด ์ํธ๋ฆฌ๋ ๊ทธ ์ฆ์ ์๋์ผ๋ก ์ ๊ฑฐ๋ ๊ฒ์ด๋ค. ๋จ, WeakHashMap์ ์ด๋ฌํ ์ํฉ์์๋ง ์ ์ฉํ๋ค.
WeakHashMap์ ์ฝํ ์ฐธ์กฐ(weak reference) - ๊ธฐ๋ณธ์ ์ผ๋ก HashMap๊ณผ ์ ์ฌํ์ง๋ง ํค์ ๋ํ ์ฐธ์กฐ๊ฐ ์ฝํ์ฐธ์กฐ(weak reference)๋ก ์ ์ฅ๋๋ ๊ฒ์ด ํน์ง์ด๋ค. - ์ฝํ ์ฐธ์กฐ๋ WeakHashMap์ ํค๋ก ์ฌ์ฉ๋๋ ๊ฐ์ฒด์ ๋ํ ์ ์ผํ ์ฐธ์กฐ๊ฐ WeakHashMap ๋ด๋ถ์๋ง ์์ด ์ผ๋ฐ์ ์ธ ์ฐธ์กฐ์ ๋ฌ๋ฆฌ ๊ฐ๋น์ง ์ปฌ๋ ํฐ์ ์ํด ์ธ์ ๋ ์ง ํ์๋ ์ ์๋ค๋ ํน์ง์ด์๋ค. |
import java.util.WeakHashMap;
public class Example {
public static void main(String[] args) {
WeakHashMap<Object, String> weakMap = new WeakHashMap<>();
Object key = new Object();
weakMap.put(key, "value");
System.out.println("Before nulling key: " + weakMap);
key = null; // key์ ๋ํ strong reference๋ฅผ ์ ๊ฑฐ
System.gc(); // ๊ฐ๋น์ง ์ปฌ๋ ํฐ ํธ์ถ
System.out.println("After GC: " + weakMap); // map ์ ๊ฑฐ
}
}
4. ์บ์์์์ ๋ฉ๋ชจ๋ฆฌ ๋์ ํด๊ฒฐ๋ฐฉ๋ฒ
- ์บ์๋ฅผ ๋ง๋ค ๋ ๋ณดํต์ ์บ์ ์ํธ๋ฆฌ์ ์ ํจ ๊ธฐ๊ฐ์ ์ ํํ ์ ์ํ๊ธฐ ์ด๋ ต๋ค. ๋ฐ๋ผ์, ์๊ฐ์ด ์ง๋ ์๋ก ์ํธ๋ฆฌ์ ๊ฐ์น๋ฅผ ๋จ์ด๋จ๋ฆฌ๋ ๋ฐฉ์์ ํํ ์ฌ์ฉํ๋ค.
- ์ด๋ฐ ๋ฐฉ์์์๋ ์ฐ์ง ์๋ ์ํธ๋ฆฌ๋ฅผ ์ด๋ฐ๊ธ ์ฒญ์ํด์ค์ผ ํ๋ค.
- ScheduledThreadPoolExecutor ๊ฐ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ค๋ ๋๋ฅผ ํ์ฉํ๊ฑฐ๋ ์บ์์ ์ ์ํธ๋ฆฌ๋ฅผ ์ถ๊ฐํ ๋ ๋ถ์ ์์ ์ผ๋ก ์ํํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
- LinkedHashMap์ removeEldestEntry ๋ฉ์๋๋ฅผ ์จ์ ํ์์ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ๋ค.
- ๋ ๋ณต์กํ ์บ์๋ฅผ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด java.lang.ref ํจํค์ง๋ฅผ ์ง์ ํ์ฉํด์ผ ํ ๊ฒ์ด๋ค.
LinkedHashMap - HashMap๊ณผ ์ ์ฌํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ฉด์ ์ถ๊ฐ๋ก ์ฐ๊ฒฐ ๋ชฉ๋ก์ ํตํด ํค-๊ฐ ์์ ์ฝ์ ์์ ๋๋ ์ก์ธ์ค ์์๋ฅผ ์ ์งํ๋ค. - ์ด๋ฌํ ์์ ์ ์ง ๊ธฐ๋ฅ์ ์บ์ ๊ตฌํ๊ณผ ๊ฐ์ ํน์ ์ ์ค์ผ์ด์ค์์ ์ ์ฉํ๊ฒ ์ฌ์ฉ๋๋ค. 1. ์์ ๋ณด์ฅ: - LinkedHashMap์ ํค-๊ฐ ์์ ์ฝ์ ์์๋ฅผ ๊ธฐ์ตํ๋ค. - ๋ฐ๋ผ์ ๋ฐ๋ณต์๋ฅผ ์ฌ์ฉํ์ฌ ๋งต์ ์ํํ ๋ ํค-๊ฐ ์์ด ์ฝ์ ๋ ์์๋๋ก ๋ฐํ๋๋ค. 2.์ก์ธ์ค ์์ ๋ชจ๋: - LinkedHashMap์ ์ก์ธ์ค ์์ ๋ชจ๋๋ฅผ ์ ํ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค. - ์ด ๋ชจ๋์์๋ get๊ณผ put ์ฐ์ฐ์ด ์ํ๋ ๋๋ง๋ค ํด๋น ํญ๋ชฉ์ด ์ฐ๊ฒฐ ๋ชฉ๋ก์ ๋์ผ๋ก ์ด๋ํ๋ค. - ์ด ๊ธฐ๋ฅ์ ์ต๊ทผ์ ์ก์ธ์คํ ํญ๋ชฉ์ ๋งต์ ๋์ ์ ์งํ๋ ๋ฐ ์ฌ์ฉ๋ ์ ์์ผ๋ฏ๋ก, LRU(Least Recently Used) ์บ์ ๊ตฌํ๊ณผ ๊ฐ์ ์๋๋ฆฌ์ค์์ ์ ์ฉํ๋ค. 3.removeEldestEntry ๋ฉ์๋: - ์ด ๋ฉ์๋๋ ๋งต์ ์ ํญ๋ชฉ์ด ์ถ๊ฐ๋ ๋๋ง๋ค ํธ์ถ๋๋ค. - ์ด ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ๋งต์ ํฌ๊ธฐ๊ฐ ํน์ ์๊ณ๊ฐ์ ์ด๊ณผํ๋ฉด ๊ฐ์ฅ ์ค๋๋ ํญ๋ชฉ์ ์๋์ผ๋ก ์ ๊ฑฐํ๋ ๋ก์ง์ ๊ตฌํํ ์ ์๋ค. |
import java.util.LinkedHashMap;
import java.util.Map;
// ์บ์์ ์ ์ํธ๋ฆฌ๋ฅผ ์ถ๊ฐํ ๋ ๋ถ์์์
์ผ๋ก ์ํํ๋ ๋ฐฉ๋ฒ ์์
public class Example {
public static void main(String[] args) {
// LRU ์บ์๋ก ๋์ํ๋ LinkedHashMap
int cacheSize = 5;
LinkedHashMap<String, String> lruCache = new LinkedHashMap<String, String>(16, 0.75f, true) {
//true : ์ก์ธ์ค ์์ ๋ชจ๋(accessOrder) ํ์ฑํ
@Override
protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
return size() > cacheSize;
//true : ๊ฐ์ฅ ์ค๋๋ ํญ๋ชฉ ์ ๊ฑฐ, false : ์ ๊ฑฐ์๋จ
}
};
for (int i = 1; i <= 10; i++) {
lruCache.put("key" + i, "value" + i);
}
System.out.println(lruCache); // ๊ฐ์ฅ ์ต๊ทผ์ ์ถ๊ฐ๋ 5๊ฐ์ ํญ๋ชฉ๋ง ์ถ๋ ฅ
}
}
5. ๋ฆฌ์ค๋(listener) ๋๋ ์ฝ๋ฐฑ(callback)์์์ ๋ฉ๋ชจ๋ฆฌ ๋์
- ํด๋ผ์ด์ธํธ๊ฐ ์ฝ๋ฐฑ์ ๋ฑ๋ก๋ง ํ๊ณ ๋ช ํํ ํด์งํ์ง ์๋๋ค๋ฉด, ๋ญ๊ฐ ์กฐ์นํด์ฃผ์ง ์๋ ํ ์ฝ๋ฐฑ์ ๊ณ์ ์์ฌ๊ฐ ๊ฒ์ด๋ค.
- ์ด๋ด ๋ ์ฝ๋ฐฑ์ ์ฝํ ์ฐธ์กฐ(weak reference)๋ก ์ ์ฅํ๋ฉด ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ฆ์ ์๊ฑฐํด๊ฐ๋ค. (ex. WeakHashMap์ ํค๋ก ์ ์ฅํ๋ฉด ๋๋ค.)
import java.util.WeakHashMap;
interface EventListener {
void onEvent(String event);
}
class EventManager {
// ๋ฆฌ์ค๋๋ฅผ WeakHashMap์ ํค๋ก ์ ์ฅํ์ฌ ์ฝํ ์ฐธ์กฐ๋ฅผ ์ ์ง
private WeakHashMap<EventListener, Boolean> listeners = new WeakHashMap<>();
public void registerListener(EventListener listener) {
listeners.put(listener, Boolean.TRUE);
}
public void fireEvent(String event) {
for (EventListener listener : listeners.keySet()) {
listener.onEvent(event);
}
}
}
public class Example {
public static void main(String[] args) {
EventManager manager = new EventManager();
// ๋ฆฌ์ค๋๋ฅผ ๋ฑ๋ก
EventListener listener = event -> System.out.println("Received event: " + event);
manager.registerListener(listener);
// ์ด๋ฒคํธ ๋ฐ์
manager.fireEvent("Test Event 1");
// ๋ฆฌ์ค๋ ์ฐธ์กฐ๋ฅผ ์ ๊ฑฐ
listener = null;
// ๊ฐ๋น์ง ์ปฌ๋ ํฐ๋ฅผ ํํธ๋ก ์คํ
System.gc();
// ์ด๋ฒคํธ ๋ฐ์
manager.fireEvent("Test Event 2"); // ์ด์ ๋ฆฌ์ค๋๋ ๋ ์ด์ ์ถ๋ ฅ๋์ง ์๋๋ค.
}
}
๋ฐ์ํ
'๐ป Java Study > Java ์ด๋ก ์ ๋ฆฌ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Comments