quilt code
[고급자바] Thread(5) 본문
1. 스레드에서 데이터를 공통으로 사용하는 방법
스레드에서 데이터를 공통으로 사용하는 방법 |
| 1. 공통으로 사용할 데이터를 클래스로 정의한다. |
| 2. 공통으로 사용할 클래스의 인스턴스를 만든다. |
| 3. 이 인스턴스를 각각의 스레드에 넘겨준다. |
| 4. 각각의 스레드는 이 인스턴스의 참조값을 지정한 변수를 이용하여 공통 데이터를 사용한다. |
| 예) 원주율을 계산하는 스레드가 있고, 계산된 원주율을 출력하는 스레드가 있다. 원주율을 계산한 후 이 값을 출력하는 프로그램을 작성하시오. (이 때 원주율을 저장하는 객체가 필요하다) |
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public static void main(String[] args) {
ShareData sd = new ShareData();
Thread th1 = new CalcPIThread(sd);
Thread th2 = new PrintPIThread(sd);
th1.start();
th2.start();
}
|
cs |
2. 원주율
| volatile | 선언된 변수를 컴파일러의 최적화 대상에서 제외시킨다. 즉, 값이 변경되는 즉시 변수에 적용시킨다. 멀티스레드 환경에서 하나의 변수가 완벽하게 한번에 작동하도록 보장하는 키워드(일종의 동기화) |
1) 원주율을 관리하는 클래스 (공통으로 사용할 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class ShareData {
private double result; // 원주율이 저장될 변수
volatile private boolean isOK; // 원주율 계산이 완료되었는지를 확인하기 위한 변수
public double getResult() {
return result;
}
public void setResult(double result) {
this.result = result;
}
public boolean isOK() {
return isOK;
}
public void setOK(boolean isOK) {
this.isOK = isOK;
}
}
|
cs |
2) 원주율 계산하는 스레드
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
class CalcPIThread extends Thread {
private ShareData sd;
public CalcPIThread(ShareData sd) {
this.sd = sd;
}
@Override
public void run() {
/*
* 원주율 = (1/1 - 1/3 + 1/5 - 1/7 + 1/9 ....) * 4;
* 1 - 3 + 5 - 7 + 9 => 분모
* 0 1 2 3 4 => 2로 나눈 몫
*/
double sum = 0.0;
for(int i=1; i<=15000000; i+=2) {
if( ((i/2) % 2) == 0) { // 2로 나눈 몫이 짝수이면... +
sum += (1.0/i);
} else {
sum -= (1.0/i);
}
}
sd.setResult(sum * 4); // 계산된 원주율 공통객체에 저장하기
sd.setOK(true); // 계산이 완료되었음을 저장함.
}
}
|
cs |
3) 계산된 원주율을 출력하는 스레드
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class PrintPIThread extends Thread {
private ShareData sd;
public PrintPIThread(ShareData sd) {
this.sd = sd;
}
@Override
public void run() {
while(true) {
if(sd.isOK()) {
break;
}
}
System.out.println();
System.out.println("계산된 원주율 : " + sd.getResult());
System.out.println(" PI : " + Math.PI);
}
}
|
cs |
3. SyncThread
|
1
2
3
4
5
6
7
8
9
10
11
12
|
public class T15SyncThreadTest {
public static void main(String[] args) {
ShareObject sObj = new ShareObject();
Thread th1 = new WorkThread("1번 스레드", sObj);
Thread th2 = new WorkThread("2번 스레드", sObj);
th1.start();
th2.start();
}
}
|
cs |
1) 공통으로 사용할 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class ShareObject {
private int sum = 0;
// 동기화 하는 방법1 : 메소드 자체에 동기화 설정하기
// public synchronized void add() {
public synchronized void add() {
for(int i= 0; i<1000000000; i++) {
}
// 동기화 하는 방법2 : 동기화 블럭으로 설정하기
// mutex : Mutual exclusion Object (상호 배제: 동시 접근 차단)
synchronized (this) {
int n = sum;
n += 10;
sum = n;
System.out.println(Thread.currentThread().getName() + " 합계: " + sum);
}
}
}
|
cs |
2) 작업을 수행하는 스레드
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class WorkThread extends Thread {
private ShareObject sObj;
public WorkThread(String name, ShareObject sObj) {
super(name);
this.sObj = sObj;
}
@Override
public void run() {
for(int i=1; i<=10; i++) {
synchronized (sObj) {
sObj.add();
}
}
}
}
|
cs |
3) 은행의 입출금을 스레드로 처리하는 예제 (synchronized를 이용한 동기화 처리)
①
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public class T16SyncAccountTest {
public static void main(String[] args) {
SyncAccount sAcc = new SyncAccount();
sAcc.deposit(10000);
Thread th1 = new BankThread(sAcc);
Thread th2 = new BankThread(sAcc);
th1.start();
th2.start();
}
}
|
cs |
② 은행의 입출금을 관리하기 위한 클래스
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
class SyncAccount {
private int balance; //잔액
public int getBalance() {
return balance;
}
// 입금 처리를 수행하는 메소드
public void deposit(int money) {
balance += money;
}
// 출금을 처리하는 메소드(출금 성공: true, 출금 실패: false반환)
// 동기화 영역에서 호출하는 메소드로 동기화 처리를 해주어야 한다.
synchronized public boolean withdraw(int money) {
if(balance >= money) {
for(int i=1; i<=1000000000; i++) { // 시간 때우기 용
}
balance -= money;
System.out.println("메소드 안에서 balance = " + getBalance());
return true;
} else {
return false;
}
}
}
|
cs |
③ 은행 업무를 처리하는 스레드
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class BankThread extends Thread {
private SyncAccount sAcc;
public BankThread(SyncAccount sAcc) {
this.sAcc = sAcc;
}
@Override
public void run() {
boolean result = sAcc.withdraw(6000); // 6000원 인출
System.out.println("스레드 안에서 result = " + result + ", balance = " + sAcc.getBalance());
}
}
|
cs |
'daily > 고급자바' 카테고리의 다른 글
| [고급자바] IO (1) (0) | 2023.02.13 |
|---|---|
| [고급자바] Thread(6) (0) | 2023.02.13 |
| [고급자바] Thread (4) (0) | 2023.02.10 |
| [고급자바] 컴퓨터와 가위바위보 프로그램 (0) | 2023.02.07 |
| [고급자바] Thread(3) (0) | 2023.02.07 |