관리 메뉴

거니의 velog

230904_스레드 5 본문

대덕인재개발원_자바기반 애플리케이션

230904_스레드 5

Unlimited00 2023. 9. 4. 13:54

[ThreadTest16.java]

package kr.or.ddit.basic;

// 은행의 입출금을 쓰레드로 처리하는 예제

public class ThreadTest16 { // 공통 객체
	
	private int balance; // 잔액이 저장될 변수
	
	public int getBalance() {
		return balance;
	}
	
	public void setBalance(int balance) {
		this.balance = balance;
	}
	
	// 입금을 처리하는 메서드
	public void deposit(int money) {
		balance += money;
	}
	
	// 출금을 처리하는 메서드 (반환값 : 출금 성공 => true, 출금 실패 => false)
	public synchronized boolean withdraw(int money) {
		if(balance >= money) {
			for(int i=1; i<=100000000; i++) { // 시간 지연용
				int a = i + 3;
			}
			
			balance -= money;
			System.out.println("메서드 안에서 balance = " + balance);
			return true;
		}else {
			return false;
		}
	}

	public static void main(String[] args) {
		
		ThreadTest16 account = new ThreadTest16();
		account.setBalance(10000); // 잔액을 10000원으로 셋팅
		
		// 익명 구현체로 쓰레드 구현
		Runnable test = new Runnable() {
			@Override
			public void run() {
				boolean result = account.withdraw(6000); // 6000원 출금하기
				System.out.println("쓰레드 안에서 result = " + result + ", 잔액 = " + account.getBalance());
			}
		};
		//----------------------------------------------------
		
		// 익명 구현체를 이용한 Thread 객체 생성
		Thread th1 = new Thread(test);
		Thread th2 = new Thread(test);
		
		th1.start();
		th2.start();
		
	}

}


[ThreadTest17.java]

package kr.or.ddit.basic;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

public class ThreadTest17 {
	
	private static Vector<Integer> vec = new Vector<Integer>();
	
	// 동기화 처리가 되지 않은 List
	private static List<Integer> list1 = new ArrayList<Integer>();

	public static void main(String[] args) {
		
		// 익명 구현체로 쓰레드 구현
		Runnable r = new Runnable() {
			@Override
			public void run() {
				for(int i=0; i<10000; i++) {
//					vec.add(i);
					list1.add(i);
				}
			}
		};
		//----------------------------------------
		
		Thread[] thArr = new Thread[] {
			new Thread(r),
			new Thread(r),
			new Thread(r),
			new Thread(r),
			new Thread(r)
		};
		
		for(Thread th : thArr) {
			th.start();
		}
		
		for(Thread th : thArr) {
			try {
				th.join();
			} catch (InterruptedException e) {
				// TODO: handle exception
			}
		}
		
//		System.out.println("vec의 개수 : " + vec.size()); // vec의 개수 : 50000, 내부적으로 동기화 처리가 잘 되어 있음.
		System.out.println("list1의 개수 : " + list1.size()); // 내부적으로 동기화 처리가 안되어 있어서 오류가 남.
		// ArrayList도 배열과 같다. 기본적 크기는 10개. 그리고 데이터 추가하면서 10개가 넘어가면 현재 크기의 2배로 만듦.
		// add() 메서드가 배열의 크기가 새로 넣을 데이터보다 작으면 배열 크기를 늘리고 넣음. 
		// 쓰레드로 작업하면 여러 쓰레드가 동작하므로 원래 데이터 크기가 부족해서 큰 배열 만들고 원래 데이터 복사하는 와중에 다른 쓰레드로 제어가 넘어가면 배열 크기가 크므로 그냥 데이터 추가해버림. 이런 식의 반복.
		
	}

}


synchronized 메서드1() {
	~~~
	wait();
	~~~
}
		
synchronized 메서드2() {
	~~~
	notify();
	~~~
}

[ThreadTest18.java]

package kr.or.ddit.basic;

/*
 * wait(), notify()를 이용한 두 쓰레드에서 번갈아 한번씩 실행하는 예제
 * ( wait(), notify(), notifyAll()은 동기화 영역에서만 사용 가능하다. )
 */

public class ThreadTest18 {

	public static void main(String[] args) {
		
		WorkObject workObj = new WorkObject();
		
		ThreadA thA = new ThreadA(workObj);
		ThreadB thB = new ThreadB(workObj);
		
		thA.start();
		thB.start();
		
	}

}

// 공통으로 사용할 class
class WorkObject {
	
	public synchronized void methodA() {
		System.out.println("methodA() 메서드 실행 중...");
		
		this.notify();
		try {
			this.wait();
		} catch (InterruptedException e) {
			// TODO: handle exception
		}
	}
	
	public synchronized void methodB() {
		System.out.println("methodB() 메서드에서 작업 중...");
		
		notify();
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO: handle exception
		}
	}
	
}

// WorkObject의 methodA() 메서드만 호출하는 쓰레드
class ThreadA extends Thread {
	private WorkObject workObj;
	
	// 생성자
	public ThreadA(WorkObject workObj) {
		this.workObj = workObj;
	}

	@Override
	public void run() {
		for(int i=1; i<=10; i++) {
			workObj.methodA();
		}
		synchronized (workObj) {
			workObj.notify();
		}
	}
}

//WorkObject의 methodB() 메서드만 호출하는 쓰레드
class ThreadB extends Thread {
	private WorkObject workObj;
	
	// 생성자
	public ThreadB(WorkObject workObj) {
		this.workObj = workObj;
	}

	@Override
	public void run() {
		for(int i=1; i<=10; i++) {
			workObj.methodB();
		}
		synchronized (workObj) {
			workObj.notify();
		}
	}
}


[ThreadTest19.java]

package kr.or.ddit.basic;

public class ThreadTest19 {

	public static void main(String[] args) {
		
		// 공통 객체 생성
		DataBox box = new DataBox();
		
		ProducerThread th1 = new ProducerThread(box);
		ConsumerThread th2 = new ConsumerThread(box);
		
		th1.start();
		th2.start();
		
	}

}

// 데이터를 공통으로 사용하는 class
class DataBox {
	
	private String value;

	/*
	 * value값이 null이면 value에 문자열이 채워질 때까지 기다리고
	 * value에 값이 있으면 해당 문자열을 반환한다.
	 * (이 때, 반환 후에는 value값을 null로 만든다.)
	 */
	public synchronized String getValue() {
		if(value == null) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO: handle exception
			}
		}
		
		// value에 데이터가 있을 때의 처리 내용을 작성한다.
		String temp = value;
		System.out.println("쓰레드가 읽은 데이터 : " + temp);
		value = null;
		
		notify();
		
		return temp;
	}

	/*
	 * value변수에 값이 있으면 value가 null이 될 때까지 기다린다.
	 * value가 null이 되면 새로운 데이터값을 value에 저장한다.
	 */
	public synchronized void setValue(String value) {
		if(this.value != null) {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO: handle exception
			}
		}
		
		// this.value의 값이 null일 때 처리하는 내용을 작성한다.
		this.value = value;
		System.out.println("Thread에서 새로 저장한 데이터 : " + value);
		
		notify();
	}
	
}

// 데이터를 넣어주는 쓰레드
class ProducerThread extends Thread {
	private DataBox box;
	
	// 생성자
	public ProducerThread(DataBox box) {
		this.box = box;
	}

	@Override
	public void run() {
		for(int i=1; i<=3; i++) {
			box.setValue("저장용 데이터 " + i);
		}
	}
}

// 데이터를 꺼내서 사용하는 쓰레드
class ConsumerThread extends Thread {
	private DataBox box;
	
	// 생성자
	public ConsumerThread(DataBox box) {
		this.box = box;
	}
	
	@Override
	public void run() {
		for(int i=1; i<=3; i++) {
			String data = box.getValue();
		}
	}
}


 

'대덕인재개발원_자바기반 애플리케이션' 카테고리의 다른 글

230906_입출력 2  (0) 2023.09.06
230905_입출력 1  (0) 2023.09.04
230901_스레드 4  (0) 2023.09.01
230831_스레드 3  (0) 2023.08.31
230830_스레드 2  (0) 2023.08.29