質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

5311閲覧

スレッドの使い方について、口座システムを作りたい

M.M.O-05

総合スコア15

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/12/09 05:32

###前提・実現したいこと
Javaを用いて、二人(husbandとwife)が100円の出入金を繰り返すプログラムを2つのスレッドを使ってつくりたいのですが、「Thread[Thread main]が出金or入金されました。」という実行表示を
husbandが100円入金しました。
husbandが100円出金しました。
wifeが100円入金しました。
wifeが100円出金しました。
と表示されるようなプログラムにするためには、Accountクラスをどう処理したらよろしいでしょうか。
教科書に沿ってやっていてもなかなかわからないので、
ぜひよろしくお願いします。
できるだけ具体的に示してもらえると助かります。
###発生している問題・エラーメッセージ

エラーメッセージ

###該当のソースコード

lang

1package thread; 2 3public class Account{ 4 5 private int balance = 0; 6 public void deposit(int money){ 7 int currentBalance = balance; 8 System.out.println(Thread.currentThread()+"が入金されました。"); 9 } 10 public void withdraw(int money){ 11 balance += money; 12 System.out.println(Thread.currentThread()+"が出金されました。"); 13 14 15 } 16 17}

lang

1package thread; 2 3public class User extends Thread { 4 Account account; 5 public User (Account account){ 6 this.account = account; 7 } 8 @Override 9 public void run(){ 10 while(true){ 11 account.deposit(100); 12 try { 13 Thread.sleep((long)Math.random()*1000000000); 14 } catch (InterruptedException e) { 15 // TODO 自動生成された catch ブロック 16 e.printStackTrace(); 17 } 18 account.withdraw(-100); 19 try { 20 Thread.sleep((long)Math.random()*1000000000); 21 } catch (InterruptedException e) { 22 // TODO 自動生成された catch ブロック 23 e.printStackTrace(); 24 } 25 } 26 } 27 public static void main(String[] args) { 28 Account account = new Account(); 29 User husband = new User(account); 30 User wife = new User(account); 31 husband.start(); 32 wife.start(); 33 34 35 } 36 37} 38

###試したこと
課題に対してアプローチしたことを記載してください

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

  • 表示

deposit, withdrawにUserも引数に加え、入出金の際にUserの名前を金額とともに表示します。

  • 同期

複数のスレッドで実行するのでbalanceの値に矛盾がでないよう、deposit, withdrawは同期する必要があります。簡単に行うにはこの2つのインスタンスメソッドをsynchronizedにすればよいです。

以上でお望みのことはできますが・・・
夫婦がそれぞれ自分が稼いだ分を等しく使うだけなのでスレッドプログラミングの題材としては面白みに欠けます。そこで問題を「夫はたまに倹約する。妻はもし引き出せるなら200円引き出し、残高が足りないなら100円引き出す」というふうに変えてみると、口座が破たんしないように夫婦がいかに生活するかが観察できます。そのためには以下の配慮が必要です。

  • 銀行口座(Account)

残金が不足している場合はwithdrawメソッドで入金されるまで待つのではなく失敗させます。そうすれば引き出しを行う側の都合によって引き出せるまで待ったり、引き出し金額を少なくするといった選択の幅ができます。

お望みの条件とは異なるプログラムになりますが、コードは例えば以下のようになります。

java

1import java.util.Random; 2 3class Account { 4 int balance = 0; 5 6 public synchronized void deposite(User who, int amount) { 7 balance += amount; 8 System.out.format("%sが%d円入金しました。\n", who.getName(), amount); 9 notifyAll(); // 入金待ちUserがいたとき入金されたことを通知 10 } 11 12 public synchronized boolean withdraw(User who, int amount) { 13 if (balance < amount) 14 return false; 15 balance -= amount; 16 System.out.format("%sが%d円出金しました。\n", who.getName(), amount); 17 return true; 18 } 19} 20 21abstract class User extends Thread { 22 Account account; 23 24 protected User(String name, Account account) { 25 super(name); 26 this.account = account; 27 } 28 29 // 引き出せるまで待ち続ける。無茶な金額を入れると無限に帰ってこないので注意。 30 void withdrawAndWait(int amount) throws InterruptedException { 31 while (!account.withdraw(this, amount)) { 32 synchronized (account) { 33 account.wait(); 34 } 35 } 36 } 37 38 @Override public void run() { 39 try { 40 for (;;) { 41 life(); 42 } 43 } catch (InterruptedException e) { 44 System.out.println("interrupted"); 45 } 46 } 47 48 protected abstract void life() throws InterruptedException; 49} 50 51class Husband extends User { 52 Random rnd = new Random(); 53 54 Husband(Account account) { super("husband", account); } 55 56 @Override protected void life() throws InterruptedException { 57 account.deposite(this, 100); 58 sleep(1000); 59 if (rnd.nextBoolean()) 60 withdrawAndWait(100); 61 else 62 System.out.println("お小遣いなしですか・・・"); 63 } 64} 65 66class Wife extends User { 67 Wife(Account account) { super("wife", account); } 68 69 @Override protected void life() throws InterruptedException { 70 account.deposite(this, 100); 71 sleep(1000); 72 if (account.withdraw(this, 200)) { 73 System.out.println("使わなくっちゃ・・・"); 74 } else { 75 withdrawAndWait(100); 76 } 77 } 78} 79 80public class MarriedLife { 81 public static void main(String[] args) { 82 Account account = new Account(); 83 User husband = new Husband(account); 84 User wife = new Wife(account); 85 husband.start(); 86 wife.start(); 87 } 88}

投稿2016/12/09 11:24

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2016/12/09 12:10

コード例にアクセス修飾子(publicなど)やブロックの中括弧等々いいかげんな部分もあります。すみませんがコードのおかしなところは適宜読み替えていただければと思います。
guest

0

以下のようなコードでできるのではないでしょうか

java

1import java.util.Random; 2 3class Account { 4 5 private static int a = 0; 6 7 private static int balance = 0; 8 9 public synchronized void deposit(int money, String name) { 10 while (a != 0) { 11 try { 12 13 wait(); 14 } catch (InterruptedException e) { 15 16 } 17 } 18 notify(); 19 a--; 20 balance += money; 21 System.out.println(name + "が100円入金し、" + balance + "円になりました。"); 22 } 23 24 public synchronized void withdraw(int money, String name) { 25 while (a == 0) { 26 try { 27 28 wait(); 29 } catch (InterruptedException e) { 30 31 } 32 } 33 notify(); 34 a++; 35 balance -= money; 36 System.out.println(name + "が100円出金し、" + balance + "円になりました。"); 37 38 } 39 40} 41 42public class UO extends Thread { 43 Random rnd = new Random(); 44 45 Account account; 46 47 String name = ""; 48 49 public UO(Account account, String name) { 50 this.account = account; 51 this.name = name; 52 } 53 54 @Override 55 public void run() { 56 int co = 0; 57 while (true) { 58 co++; 59 if (co == 20) 60 break; 61 account.deposit(100, name); 62 try { 63 Thread.sleep((long) rnd.nextInt(1000) + 1); 64 } catch (InterruptedException e) { 65 66 e.printStackTrace(); 67 } 68 account.withdraw(100, name); 69 try { 70 Thread.sleep((long) rnd.nextInt(1000) + 1); 71 } catch (InterruptedException e) { 72 73 e.printStackTrace(); 74 } 75 } 76 } 77 78 public static void main(String[] args) { 79 Account account = new Account(); 80 UO husband = new UO(account, "husband"); 81 UO wife = new UO(account, "wife"); 82 husband.start(); 83 wife.start(); 84 85 } 86 87}

投稿2016/12/09 07:27

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

下記の修正を行うことでできますよ。
・Accountにアカウント名フィールドを追加する。
・コンストラクタでアカウント名を初期化する。
・メッセージの表示箇所でアカウント名を使用する。

投稿2016/12/09 06:22

編集2016/12/09 06:23
yona

総合スコア18155

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問