1.synchronized 키워드를 사용하여 메소드 작성 - 동기화 메소드(synchronized Method)
형식) 접근제한자 synchronized 반환형 메소드명(자료형 변수명, ...){명령; ...}
형식) synchronized(공유 객체) {객체.메소드명(값, ...); ...}
// 은행계좌정보(잔액)를 저장하기 위한 클래스
// => 입금 및 출금 관련 메소드 작성
public class Account {
private int balance;
public Account() {
}
public Account(int balance) {
this.balance = balance;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
// 입금 처리 메소드 - 매개변수로 입금자와 입금액을 전달받아 처리
// 스레드 동기화 처리(synchronized) 1번 방법
public synchronized void deposit(String name, int ammount) {
balance += ammount;
System.out.println("[입금] " + name + "님이 " + ammount + "원을 입금하여 잔액은 " + balance + "원 입니다.");
}
// 출금 처리 메소드 - 매개변수로 출금자와 출금액을 전달받아 처리
public void withdraw(String name, int ammount) {
if(balance < ammount){
System.out.println("[에러] " + name + "님 " + "잔액이 " + balance + "원 남아 " + ammount + "원을 출금할 수 없습니다.");
return;
}
balance -= ammount;
System.out.println("[출금] " + name + "님이 " + ammount + "원을 출금하여 잔액은 " + balance + "원 입니다.");
}
}
// 은행계좌를 사용할 수 있는 사용자정보(은행계좌정보, 사용자명)를 저장하기 위한 클래스
public class AccountUser extends Thread {
// 생성자 또는 Setter 메소드로 필드에 객체를 저장하여 포함관계 완성
private Account account;
private String userName;
public AccountUser(Account account, String userName) {
this.account = account;
this.userName = userName;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
// 새로운 스레드로 실행될 명령 작성 - 입금 또는 출금 관련 명령 작성
@Override
public void run() {
// 스레드 동기화 1번 방법)(메소드에서 처리)
// account.deposit(userName, 5000);
// 스레드 동기화 2번 방법
synchronized (account){ // 메소드에서 synchronized가 안 되어있을 때
account.withdraw(userName, 5000);
}
// Thread.sleep() 사용 할 경우
// try {
// // InterruptedException 발생할 수 있기 때문에 try catch로 예외처리
// Thread.sleep(500);
// } catch (InterruptedException e) {
// // throw new RuntimeException(e);
// e.printStackTrace();
// }
}
}
public class AccountUserApp {
public static void main(String[] args) {
// Account 클래스로 객체를 생성하여 참조변수에 저장 - 은행 게좌 생성
Account account = new Account(10000);
// AccountUser 클래스로 객체를 생성하여 참조변수에 저장 - 동일한 은행계좌를 사용할 수 있는 다수의 사용자 생성
AccountUser userOne = new AccountUser(account, "홍길동");
AccountUser userTwo = new AccountUser(account, "임꺽정");
AccountUser userThree = new AccountUser(account, "전우치");
/*
// 사용자(AccountUser 객체)로부터 은행계좌(Account 객체)를 제공받아 입금 처리(메소드 호출)
// => 단일스레드(main 스레드)를 이용해 객체를 참조해 메소드 호출
// => 단일스레드를 사용하므로 동시 입금 처리 불가능
userOne.getAccount().deposit(userOne.getUserName(), 5000);
userTwo.getAccount().deposit(userTwo.getUserName(), 5000);
userThree.getAccount().deposit(userThree.getUserName(), 5000);
*/
// 새로운 스레드를 생성하여 AccountUser 클래스의 run() 메소드에 명령 실행
// new AccountUser(account, "홍길동").start();
// new AccountUser(account, "임꺽정").start();
// new AccountUser(account, "전우치").start();
userOne.start();
userTwo.start();
userThree.start();
}
}