#10 effective java: item 7
This commit is contained in:
37
effective-java/src/main/java/com/example/effectivejava/chapter01/item07/cache/CacheKey.java
vendored
Normal file
37
effective-java/src/main/java/com/example/effectivejava/chapter01/item07/cache/CacheKey.java
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.example.effectivejava.chapter01.item07.cache;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class CacheKey {
|
||||
|
||||
private Integer value;
|
||||
|
||||
private LocalDateTime created;
|
||||
|
||||
public CacheKey(Integer value) {
|
||||
this.value = value;
|
||||
this.created = LocalDateTime.now();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this.value.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.value.hashCode();
|
||||
}
|
||||
|
||||
public LocalDateTime getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CacheKey{" +
|
||||
"value=" + value +
|
||||
", created=" + created +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
39
effective-java/src/main/java/com/example/effectivejava/chapter01/item07/cache/Post.java
vendored
Normal file
39
effective-java/src/main/java/com/example/effectivejava/chapter01/item07/cache/Post.java
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
package com.example.effectivejava.chapter01.item07.cache;
|
||||
|
||||
public class Post {
|
||||
|
||||
private Integer id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String content;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() {
|
||||
System.out.println("gc called");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.example.effectivejava.chapter01.item07.cache;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class PostRepository {
|
||||
|
||||
private Map<CacheKey, Post> cache;
|
||||
|
||||
public PostRepository() {
|
||||
this.cache = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
public Post getPostById(CacheKey key) {
|
||||
if (cache.containsKey(key)) {
|
||||
return cache.get(key);
|
||||
} else {
|
||||
// TODO DB에서 읽어오거나 REST API를 통해 읽어올 수 있습니다.
|
||||
Post post = new Post();
|
||||
cache.put(key, post);
|
||||
return post;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<CacheKey, Post> getCache() {
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.example.effectivejava.chapter01.item07.listener;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ChatRoom {
|
||||
|
||||
private List<WeakReference<User>> users;
|
||||
|
||||
public ChatRoom() {
|
||||
this.users = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addUser(User user) {
|
||||
this.users.add(new WeakReference<>(user));
|
||||
}
|
||||
|
||||
public void sendMessage(String message) {
|
||||
users.forEach(wr -> Objects.requireNonNull(wr.get()).receive(message));
|
||||
}
|
||||
|
||||
public List<WeakReference<User>> getUsers() {
|
||||
return users;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.example.effectivejava.chapter01.item07.listener;
|
||||
|
||||
public class User {
|
||||
|
||||
public void receive(String message) {
|
||||
System.out.println(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.example.effectivejava.chapter01.item07.stack;
|
||||
|
||||
// (36쪽의 Stack 코드에서 던지는 예외)
|
||||
public class EmptyStackException extends IllegalStateException {
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.example.effectivejava.chapter01.item07.stack;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// 코드 7-1 메모리 누수가 일어나는 위치는 어디인가? (36쪽)
|
||||
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);
|
||||
}
|
||||
|
||||
// 코드 7-2 제대로 구현한 pop 메서드 (37쪽)
|
||||
public Object pop() {
|
||||
if (size == 0)
|
||||
throw new EmptyStackException();
|
||||
Object result = elements[--size];
|
||||
elements[size] = null; // 다 쓴 참조 해제
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Stack stack = new Stack();
|
||||
for (String arg : args)
|
||||
stack.push(arg);
|
||||
|
||||
while (true)
|
||||
System.err.println(stack.pop());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.example.effectivejava.chapter01.item07.cache;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class PostRepositoryTest {
|
||||
|
||||
@Test
|
||||
void cache() throws InterruptedException {
|
||||
PostRepository postRepository = new PostRepository();
|
||||
CacheKey key1 = new CacheKey(1);
|
||||
postRepository.getPostById(key1);
|
||||
|
||||
assertFalse(postRepository.getCache().isEmpty());
|
||||
|
||||
key1 = null;
|
||||
// TODO run gc
|
||||
System.out.println("run gc");
|
||||
System.gc();
|
||||
System.out.println("wait");
|
||||
Thread.sleep(3000L);
|
||||
|
||||
assertTrue(postRepository.getCache().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void backgroundThread() throws InterruptedException {
|
||||
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
|
||||
PostRepository postRepository = new PostRepository();
|
||||
CacheKey key1 = new CacheKey(1);
|
||||
postRepository.getPostById(key1);
|
||||
|
||||
Runnable removeOldCache = () -> {
|
||||
System.out.println("running removeOldCache task");
|
||||
Map<CacheKey, Post> cache = postRepository.getCache();
|
||||
Set<CacheKey> cacheKeys = cache.keySet();
|
||||
Optional<CacheKey> key = cacheKeys.stream().min(Comparator.comparing(CacheKey::getCreated));
|
||||
key.ifPresent((k) -> {
|
||||
System.out.println("removing " + k);
|
||||
cache.remove(k);
|
||||
});
|
||||
};
|
||||
|
||||
System.out.println("The time is : " + new Date());
|
||||
|
||||
executor.scheduleAtFixedRate(removeOldCache,
|
||||
1, 3, TimeUnit.SECONDS);
|
||||
|
||||
Thread.sleep(20000L);
|
||||
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.example.effectivejava.chapter01.item07.listener;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ChatRoomTest {
|
||||
|
||||
@Test
|
||||
void charRoom() throws InterruptedException {
|
||||
ChatRoom chatRoom = new ChatRoom();
|
||||
User user1 = new User();
|
||||
User user2 = new User();
|
||||
|
||||
chatRoom.addUser(user1);
|
||||
chatRoom.addUser(user2);
|
||||
|
||||
chatRoom.sendMessage("hello");
|
||||
|
||||
user1 = null;
|
||||
|
||||
System.gc();
|
||||
|
||||
Thread.sleep(5000L);
|
||||
|
||||
List<WeakReference<User>> users = chatRoom.getUsers();
|
||||
assertEquals(1, users.size());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user