쓰레드(Thread) 동기화
📌 쓰레드(Thread) 동기화
: 둘 이상의 쓰레드가 동일한 메모리 공간에 접근할때 문제가 생기는 것을 막기 위해 사용.
📄 ThreadSynchronizationTest.java
package threadSynchronization;
class Counter {
int count = 0;
public void increment() { count++; }
public void decrement() { count--; }
public int getCount() { return count; }
}
public class ThreadSynchronizationTest {
public static Counter cnt = new Counter();
public static void main(String[] args) throws InterruptedException {
Runnable task1 = () -> {
for(int i = 0; i < 1000; i++) { cnt.increment(); }
};
Runnable task2 = () -> {
for(int i = 0; i < 1000; i++) { cnt.decrement(); }
};
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(cnt.getCount());
}
}
// 실행할 때마다 출력되는 값이 다름.
쓰레드(Thread) 동기화 방법 - 동기화(Synchronization) 메소드
📌 동기화(Synchronization) 메소드
: 두 쓰레드가 동시에 호출할 경우, 좀 더 빨리 호출한 쓰레드가 메소드를 실행하고, 다른 쓰레드는 대기하다가 먼저 호출한 쓰레드가 실행을 마치면 메소드를 실행하도록 함.
synchronized public void increment() {
count++
}
📌 한 클래스의 두 메소드에 synchronized를 선언하면, 두 메소드는 둘 이상의 쓰레드에 의해 동시에 실행될 수 없도록 동기화됨.
📄 ThreadSynchronizationTest2.java
package threadSynchronization2;
class Counter {
int count = 0;
synchronized public void increment() { count++; }
synchronized public void decrement() { count--; }
public int getCount() { return count; }
}
public class ThreadSynchronizationTest2 {
public static Counter cnt = new Counter();
public static void main(String[] args) throws InterruptedException {
Runnable task1 = () -> {
for(int i = 0; i < 1000; i++) { cnt.increment(); }
};
Runnable task2 = () -> {
for(int i = 0; i < 1000; i++) { cnt.decrement(); }
};
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(cnt.getCount()); // 0
}
}
쓰레드(Thread) 동기화 방법 - 동기화(Synchronization) 블록
📌 동기화(Synchronization) 블록
: 문장 단위로 동기화.
📄 ThreadSynchronizationTest3.java
package threadSynchronization3;
class Counter {
int count = 0;
public void increment() {
synchronized(this) { count++; }
}
public void decrement() {
synchronized(this) { count--; }
}
public int getCount() { return count; }
}
public class ThreadSynchronizationTest3 {
public static Counter cnt = new Counter();
public static void main(String[] args) throws InterruptedException {
Runnable task1 = () -> {
for(int i = 0; i < 1000; i++) { cnt.increment(); }
};
Runnable task2 = () -> {
for(int i = 0; i < 1000; i++) { cnt.decrement(); }
};
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(cnt.getCount()); // 0
}
}
쓰레드(Thread) 동기화 방법 - ReentrantLock 클래스
📌 ReentrantLock 클래스
class Test {
ReentrantLock r = new ReentrantLock();
void testMethod(int arg) {
r.lock();
...
r.unlock();
}
}
class Test {
ReentrantLock r = new ReentrantLock();
void testMethod(int arg) {
r.lock();
try {
... // 한 쓰레드에 의해 실행되는 영역.
}
finally {
r.unlock();
}
}
}
쓰레드 풀(Thread Pool)
📌 쓰레드 풀(Thread Pool)
: 안에 미리 제한된 수의 쓰레드를 생성해 두고 재활용해 사용는 기술.
java.util.concurrent 패키지.
📌 쓰레드 풀(Thread Pool) 생성 방법
newSingleThreadExecutor | - 풀 안에 하나의 쓰레드만 생성하고 유지함. - 단점 : 마지막에 전달된 작업은 가장 늦게 처리됨. |
newFixedThreadPool | - 풀 안에 인자로 전달된 수의 쓰레드를 생성하고 유지함. |
newCachedThreadPool | - 풀 안에 쓰레드의 수를 작업 수에 맞게 유동적으로 관리함. - 단점 : 빈번한 쓰레드 생성과 소멸이 이뤄질 수 있음. |
📄 ThreadPoolTest.java
package threadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolTest {
public static void main(String[] args) {
Runnable task = () -> {
int n1 = 10;
int n2 = 20;
String name = Thread.currentThread().getName();
System.out.println(name + " : " + n1 + " " + n2);
};
ExecutorService e = Executors.newSingleThreadExecutor(); // 쓰레드 풀 생성.
e.submit(task); // 작업 전달.
System.out.println("End : " + Thread.currentThread().getName());
e.shutdown();
}
}
// End : main
// pool-1-thread-1 : 10 20
+ 추가 설명
- ExecutorService e = Executors.newSingleThreadExecutor(); \
→ 쓰레드 풀 생성.
- e.submit(task);
→ 작업 전달.
풀에서 대기하던 쓰레드가 일을 실행하고, 일이 끝나면 다시 풀로 돌아가 기다림.
- e.shutdown();
→ 생성된 풀과 그 안에 존재하는 쓰레드 소멸.
'Java > Java' 카테고리의 다른 글
[Java] 쓰레드(Thread) (0) | 2022.10.24 |
---|---|
[Java] I/O 스트림 (0) | 2022.10.22 |
[Java] 예외 처리 (0) | 2022.10.22 |
[Java] 최종 연산 (0) | 2022.10.21 |
[Java] 중간 연산 - 정렬과 루핑(Looping) (0) | 2022.10.21 |
댓글