-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## 개요 - 다양한 카운터 구현체 ## 변경 사항 - [x] ✨ Feat : AtomicInteger 카운터 - [x] ✨ Feat : CompletableFuture 카운터 - [x] ✨ Feat : Synchronized 카운터 - [x] ✨ Feat : `BasicCounter` - [x] ✨ Feat : `LockCounter` - [x] ✨ Feat : `PollingCounter` - [x] ✨ Feat : `BatchingCounter` ## 추가 정보 ### 관련 이슈 Close #17 -> Close #27
- Loading branch information
Showing
29 changed files
with
868 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,50 @@ | ||
# spring-thread-concurrency | ||
[![codecov](https://codecov.io/gh/spring-templates/spring-concurrency-thread/graph/badge.svg?token=N3GEH8C5K7)](https://codecov.io/gh/spring-templates/spring-concurrency-thread) | ||
|
||
![Spring Boot](https://img.shields.io/badge/Spring%20Boot-6DB33F?logo=springboot&logoColor=white) | ||
![Java](https://img.shields.io/badge/Java-ED8B00?logoColor=white) | ||
![Gradle](https://img.shields.io/badge/Gradle-02303A?logo=gradle&logoColor=white) | ||
![JUnit5](https://img.shields.io/badge/JUnit5-25A162?logo=junit5&logoColor=white) | ||
![JaCoCo](https://img.shields.io/badge/JaCoCo-D22128?logo=jacoco&logoColor=white) | ||
![Codecov](https://img.shields.io/badge/Codecov-F01F7A?logo=codecov&logoColor=white) | ||
![GitHub Actions](https://img.shields.io/badge/GitHub%20Actions-2088FF?logo=githubactions&logoColor=white) | ||
|
||
# 관심사 | ||
|
||
- [멀티 스레드의 자원 공유 문제](https://github.com/spring-templates/spring-concurrency-thread/discussions/16) | ||
- [멀티 쓰레드 자원 업데이트 문제](https://github.com/spring-templates/spring-concurrency-thread/discussions/17) | ||
|
||
# 정보 | ||
|
||
- [동시성 기본 조건과 관심사](https://github.com/spring-templates/spring-concurrency-thread/discussions/2) | ||
|
||
# [Counter-implementation Benchmark](https://www.notion.so/softsquared/f314375356b54381a8878cf2dabd381b) | ||
|
||
> - median of 25 iterations | ||
> - nRequests: 2^21 - 1 | ||
| name | nThreads | time (ms) | memory (KB) | | ||
|-------------------|----------|-----------|-------------| | ||
| AtomicBatch | 4 | 12 | 480 | | ||
| Atomic | 1 | 14 | 318 | | ||
| AtomicBatch | 1 | 30 | 240 | | ||
| Lock | 1 | 61 | 241 | | ||
| Synchronized | 1 | 61 | 241 | | ||
| Polling | 1 | 78 | 463 | | ||
| CompletableFuture | 1 | 158 | 25710 | | ||
|
||
### AtomicBatch vs Atomic | ||
|
||
> - nThreads: AtomicBatch=4, Atomic=1 | ||
| name | nRequests | time (ms) | memory (KB) | | ||
|-------------|-----------|-----------|-------------| | ||
| AtomicBatch | 2^21 - 1 | 12 | 480 | | ||
| AtomicBatch | 2^22 - 1 | 24 | 538 | | ||
| AtomicBatch | 2^23 - 1 | 42 | 572 | | ||
| AtomicBatch | 2^30 - 1 | 5695 | 511 | | ||
| AtomicBatch | 2^31 - 1 | 11621 | 294 | | ||
| Atomic | 2^21 - 1 | 14 | 318 | | ||
| Atomic | 2^22 - 1 | 27 | 244 | | ||
| Atomic | 2^23 - 1 | 55 | 344 | | ||
| Atomic | 2^30 - 1 | 7178 | 103 | | ||
| Atomic | 2^31 - 1 | 14377 | 266 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
coverage: | ||
status: | ||
project: | ||
default: | ||
target: 40% | ||
threshold: 10% | ||
patch: | ||
default: | ||
target: 30% | ||
threshold: 10% |
8 changes: 6 additions & 2 deletions
8
src/main/java/com/thread/concurrency/SpringThreadConcurrencyApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,17 @@ | ||
package com.thread.concurrency; | ||
|
||
import com.thread.concurrency.executor.CounterBenchmark; | ||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
import org.springframework.context.ConfigurableApplicationContext; | ||
|
||
@SpringBootApplication | ||
public class SpringThreadConcurrencyApplication { | ||
|
||
public static void main(String[] args) { | ||
SpringApplication.run(SpringThreadConcurrencyApplication.class, args); | ||
ConfigurableApplicationContext context = SpringApplication.run(SpringThreadConcurrencyApplication.class, args); | ||
var performance = context.getBean(CounterBenchmark.class).benchmark(); | ||
System.out.println("|----------------------|---------------|---------------|---------------|"); | ||
System.out.println(performance); | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/com/thread/concurrency/counter/AtomicCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
@Component | ||
public class AtomicCounter implements Counter { | ||
private final AtomicInteger count = new AtomicInteger(100); | ||
|
||
@Override | ||
public void add(int value) { | ||
count.addAndGet(value); | ||
} | ||
|
||
@Override | ||
public int show() { | ||
return count.get(); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
count.set(0); | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/main/java/com/thread/concurrency/counter/CompletableFutureCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutionException; | ||
|
||
@Component | ||
public class CompletableFutureCounter implements Counter { | ||
private CompletableFuture<Integer> counter; | ||
|
||
public CompletableFutureCounter() { | ||
this.counter = new CompletableFuture<>(); | ||
counter.complete(100); | ||
} | ||
|
||
@Override | ||
public void add(int value) { | ||
synchronized (this) { | ||
counter = counter.thenApply((c) -> c + value); | ||
} | ||
} | ||
|
||
@Override | ||
public int show() { | ||
try { | ||
return counter.get(); | ||
} catch (InterruptedException | ExecutionException e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
synchronized (this) { | ||
counter = CompletableFuture.completedFuture(0); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
public interface Counter { | ||
void add(int value); | ||
|
||
int show(); | ||
|
||
void clear(); | ||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/thread/concurrency/counter/LockCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.concurrent.locks.ReentrantLock; | ||
|
||
@Component | ||
public class LockCounter implements Counter { | ||
private static final ReentrantLock lock = new ReentrantLock(); | ||
private static int count = 100; | ||
|
||
@Override | ||
public void add(int value) { | ||
lock.lock(); | ||
try { | ||
count += value; | ||
} finally { | ||
lock.unlock(); | ||
} | ||
} | ||
|
||
@Override | ||
public int show() { | ||
return count; | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
lock.lock(); | ||
try { | ||
count = 0; | ||
} finally { | ||
lock.unlock(); | ||
} | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/com/thread/concurrency/counter/PollingCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class PollingCounter implements Counter { | ||
private static int count = 100; | ||
private static volatile boolean lock = false; | ||
|
||
@Override | ||
public void add(int value) { | ||
while (true) { | ||
if (!lock) { | ||
synchronized (PollingCounter.class) { | ||
lock = true; | ||
count += value; | ||
lock = false; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public int show() { | ||
return count; | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
while (true) { | ||
if (!lock) { | ||
synchronized (PollingCounter.class) { | ||
lock = true; | ||
count = 0; | ||
lock = false; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/thread/concurrency/counter/SynchronizedCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.thread.concurrency.counter; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class SynchronizedCounter implements Counter { | ||
|
||
private int counter = 100; | ||
|
||
@Override | ||
public synchronized void add(int value) { | ||
counter += value; | ||
} | ||
|
||
@Override | ||
public synchronized int show() { | ||
return counter; | ||
} | ||
|
||
@Override | ||
public synchronized void clear() { | ||
counter = 0; | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
src/main/java/com/thread/concurrency/counter/batch/AtomicBatchCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.thread.concurrency.counter.batch; | ||
|
||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.ConcurrentMap; | ||
import java.util.concurrent.atomic.AtomicLong; | ||
import java.util.concurrent.atomic.LongAdder; | ||
|
||
@Component | ||
public class AtomicBatchCounter implements BatchCounter { | ||
private final AtomicLong counter = new AtomicLong(); | ||
private final ConcurrentMap<Long, LongAdder> batch = new ConcurrentHashMap<>(); | ||
|
||
@Override | ||
public void add(int value) { | ||
var threadId = Thread.currentThread().threadId(); | ||
batch.computeIfAbsent(threadId, k -> new LongAdder()).add(value); | ||
} | ||
|
||
@Override | ||
public int show() { | ||
return counter.intValue(); | ||
} | ||
|
||
@Override | ||
public void clear() { | ||
counter.set(0); | ||
batch.clear(); | ||
} | ||
|
||
@Override | ||
public void flush() { | ||
var threadId = Thread.currentThread().threadId(); | ||
flush(threadId); | ||
} | ||
|
||
private void flush(long threadId) { | ||
var value = batch.remove(threadId); | ||
if (value != null) { | ||
counter.addAndGet(value.longValue()); | ||
} | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/java/com/thread/concurrency/counter/batch/BatchCounter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.thread.concurrency.counter.batch; | ||
|
||
import com.thread.concurrency.counter.Counter; | ||
|
||
public interface BatchCounter extends Counter { | ||
void flush(); | ||
} |
Oops, something went wrong.