자바 멀티스레드 질문입니다.

익명 사용자의 이미지

은행 자동 출금프로그램인데요, 각자 출금한 금액의 총합과 출금횟수를 출력하는데 값이 다르게 나와서요..
아무리봐도 어느부분이 잘못된건지 모르겠습니다ㅠㅠ

public class Bank {
	static Account account = new Account();
 
	public static void main(String[] args) {
		Husband husband = new Husband(account );
		Wife wife = new Wife(account);
 
		 Thread t1 = new Thread(husband);
         Thread t2 = new Thread(wife);
 
         for(int i=0; i<account.bank;i++) {
         t1.setName("남편");
         t2.setName("아내");
 
         t1.start();
         t2.start();
         try {
        	 t1.join();
        	 t2.join();
         }catch(InterruptedException e) {
         }
         }
 
         System.out.println("남편 출금 횟수: "+husband.gethCnt());
         System.out.println("남편 총 출금액: "+husband.gethMoney());
         System.out.println("아내 출금 횟수: "+wife.getCnt());
         System.out.println("아내 총 출금액: "+wife.getMoney());
	}
 
}

//스레드로 동작
import java.util.Random;
public class Husband implements Runnable{
	 Account account = new Account();
	 int hMoney=0;
	 int hCount=0;
 
	public Husband(Account account) {
		this.account=account;
	}
 
	@Override
	public void run() {
		 while(account.bank > 0){
 
	            int money = (int)(Math.random() * 3 + 1) * 10000;
	            account.withDraw(money);
	            hMoney+=money;
	            hCount++;
		 }
	    }
 
	public int gethCnt() {
		return hCount;
	}
 
	public void setCnt(int hCount) {
	this.hCount=hCount;
	}	
 
	public int gethMoney() {
		return hMoney;
	}
 
	public void sethMoney(int hMoney) {
		this.hMoney=hMoney;
	}
}

import java.util.Random;
//스레드로 동작
public class Wife implements Runnable {
	 Account account = new Account();
	 int wMoney=0;
	 int wCount=0;
	public Wife(Account account) {
		this.account = account;
	}
 
	@Override
	public void run() {
		 while(account.bank > 0){
 
 
	            int money = (int)(Math.random() * 3 + 1) * 10000;
	            account.withDraw(money);
	            wMoney+=money;
	            wCount++;
		 }
	}
	public int getCnt() {
		return wCount;
	}
	public void getCnt(int wCount) {
		this.wCount=wCount;
	}
	public int getMoney() {
		return wMoney;
	}
	public void getMoney(int wMoney) {
		this.wMoney=wMoney;
	}
 
}

// - 부부가 하나의 계좌(Account)를 공동으로 사용하고 있다.
// - 공동 계좌에는 현재 10,000,000원이 들어있다.
//공유될 클래스
import java.time.*;//현재시간을 알기위해
public class Account {
	int bank = 100000;//잔액
	int total;
	int hCount, hMoney;
	int wCount, wMoney;
 
 
	public synchronized int withDraw(int money) {
		if(bank>=money) {
			try {
				Thread thread = Thread.currentThread();
				System.out.println(thread.getName()+"출금:"+money);
				Thread.sleep(2000);
				bank-=money;
				System.out.println(LocalDateTime.now()+" |잔액:"+bank);
			}catch(InterruptedException e) {
		}
	}
		return money;
}
	public int getTotal() {
		return total;
	}
 
}

--------------- 결과 -----------------------
아내출금:10000
2019-06-07T01:41:55.658 |잔액:90000
남편출금:10000
2019-06-07T01:41:57.659 |잔액:80000
아내출금:10000
2019-06-07T01:41:59.659 |잔액:70000
남편출금:30000
2019-06-07T01:42:01.660 |잔액:40000
아내출금:20000
2019-06-07T01:42:03.661 |잔액:20000
남편출금:10000
2019-06-07T01:42:05.662 |잔액:10000
아내출금:10000
2019-06-07T01:42:07.662 |잔액:0
남편 출금 횟수: 4
남편 총 출금액: 80000
아내 출금 횟수: 4
아내 총 출금액: 50000

익명 사용자의 이미지

withDraw 호출 후 무조건 카운트와 돈을 더하게 되어 있는데
withDraw가 제대로 수행되었는지 체크하는 로직이 없어서 그런거 같네요.

if(bank>=money) {
	try {
		Thread thread = Thread.currentThread();
		System.out.println(thread.getName()+"출금:"+money);
		Thread.sleep(2000);
		bank-=money;
		System.out.println(LocalDateTime.now()+" |잔액:"+bank);
	}catch(InterruptedException e) {
}
 
int money = (int)(Math.random() * 3 + 1) * 10000;
account.withDraw(money);
hMoney+=money;
hCount++;
 
int money = (int)(Math.random() * 3 + 1) * 10000;
account.withDraw(money);
wMoney+=money;
wCount++;

emptynote의 이미지

잔액이 출금액 보다 작은 경우에도 출금 횟수와 총 출금액이 더해 지네요.

저라면 public synchronized int withDraw(int money) 를

잔액 부족이라는 예외를 던지도록 하던가 혹은 성공 유무를 반환하도록 수정하고

그에 맞게 로직을 구성할 것입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.