LoginSignup
0
2

More than 5 years have passed since last update.

[Java]ThreadとRunnable

Last updated at Posted at 2018-10-18

ステップ1,チケット販売を仮定のプログラム

1.1 Mythread 作成

1.2 main関数から起動する

以下はサンプル

class Mythread extends Thread {

    private int ticket = 5;
    @Override
    public void run() {
        for(int i =0 ; i<10 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
            if(ticket > 0 ) {
                ticket--;
                L.d("残チケット枚数は"+ticket+"枚");
            }
        }
    }
}

public class ThreadSample {

    public static void main(String[] args) {
        Mythread mythread = new Mythread();
        L.d("チケット販売開始");
        mythread.start();
    }
}

結果:
ThreadSample#main:34 thread name:main thread id:1 gentest ::チケット販売開始
Mythread#run:24 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は4枚
Mythread#run:24 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は3枚
Mythread#run:24 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は2枚
Mythread#run:24 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は1枚
Mythread#run:24 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は0枚

ステップ2,チケット販売完了後の報告(コールバック)追加

2.1 interface 作成

2.2 mainクラスにてinterface の実現

2.3 Mythreadのコンストラクタ追加

2.4 Mythreadのrunにコールバック追加

以下はサンプル

interface MyTaskResult {
    void ticketSoldout();
    void ticketRemain();
}

class Mythread extends Thread {
    private MyTaskResult myTaskResult;
    public Mythread (MyTaskResult myTaskResult) {
        this.myTaskResult = myTaskResult;
    }

    private int ticket = 5;
    @Override
    public void run() {
        for(int i =0 ; i<10 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
            if(ticket > 0 ) {
                ticket--;
                L.d("残チケット枚数は"+ticket+"枚");
            }
        }
        if(ticket>0) {
            myTaskResult.ticketRemain();
        }else {
            myTaskResult.ticketSoldout();
        }
    }
}

public class ThreadSample {

    public static void main(String[] args) {
        Mythread mythread = new Mythread(myTaskResult);
        L.d("チケット販売開始");
        mythread.start();
    }
    static MyTaskResult myTaskResult = new MyTaskResult() {

        @Override
        public void ticketSoldout() {
            L.d("お疲れ様です。");
        }

        @Override
        public void ticketRemain() {
            L.d("終わっていないの?");
        }
    };
}

結果は

ThreadSample#main:43 thread name:main thread id:1 gentest ::チケット販売開始
Mythread#run:28 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は4枚
Mythread#run:28 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は3枚
Mythread#run:28 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は2枚
Mythread#run:28 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は1枚
Mythread#run:28 thread name:Thread-0 thread id:11 gentest ::残チケット枚数は0枚
ThreadSample$1#ticketSoldout:50 thread name:Thread-0 thread id:11 gentest ::お疲れ様です。

ステップ3、多数券売機でチケットを販売する

3.1 Runnable追加(TicketBox )

3.2 Thread の数追加、Thread 名追加(代理1,2,3)

以下はサンプル

interface MyTaskResult {
    void ticketSoldout(String threadName);
    void ticketRemain(String threadName);
}

class TicketBox implements Runnable {
    private int ticket = 5;
    @Override
    public void run() {
        for(int i =0 ; i<10 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
            if(ticket > 0 ) {
                ticket--;
                L.d("残チケット枚数は"+ticket+"枚");
            }
        }
        L.d("完了 チケット:"+ticket);
    }
}

class Mythread extends Thread {
    private MyTaskResult myTaskResult;
    public Mythread (Runnable r, MyTaskResult myTaskResult,String threadName) {
        super(r);
        this.myTaskResult = myTaskResult;
        setName(threadName);
    }

    private int ticket = 5;
    @Override
    public void run() {
        super.run();
    }
}

public class ThreadSample {

    public static void main(String[] args) {
        TicketBox ticketBox = new TicketBox();
        Mythread mythread1 = new Mythread(ticketBox,myTaskResult,"代理1");
        Mythread mythread2 = new Mythread(ticketBox,myTaskResult,"代理2");
        Mythread mythread3 = new Mythread(ticketBox,myTaskResult,"代理3");
        L.d("チケット販売開始");
        mythread1.start();
        mythread2.start();
        mythread3.start();
    }
    static MyTaskResult myTaskResult = new MyTaskResult() {

        @Override
        public void ticketSoldout(String threadName) {
            L.d("お疲れ様です。"+threadName);
        }

        @Override
        public void ticketRemain(String threadName) {
            L.d("終わっていないの?"+threadName);
        }
    };
}

結果

ThreadSample#main:52 thread name:main thread id:1 gentest ::チケット販売開始
TicketBox#run:23 thread name:代理2 thread id:12 gentest ::残チケット枚数は3枚
TicketBox#run:23 thread name:代理1 thread id:11 gentest ::残チケット枚数は3枚
TicketBox#run:23 thread name:代理3 thread id:13 gentest ::残チケット枚数は3枚
TicketBox#run:23 thread name:代理1 thread id:11 gentest ::残チケット枚数は2枚
TicketBox#run:23 thread name:代理2 thread id:12 gentest ::残チケット枚数は1枚
TicketBox#run:23 thread name:代理3 thread id:13 gentest ::残チケット枚数は0枚
TicketBox#run:26 thread name:代理2 thread id:12 gentest ::完了 残チケット:0
TicketBox#run:26 thread name:代理3 thread id:13 gentest ::完了 残チケット:0
TicketBox#run:26 thread name:代理1 thread id:11 gentest ::完了 残チケット:0

問題点:
1、チケット5枚に対して、6回売ってしまった。(同期処理必要)
2、各代理は何枚発売したを統計していない

ステップ4 同期処理

class TicketBox implements Runnable {
    private int ticket = 5;
    @Override
    public void run() {
        for(int i =0 ; i<10 ; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO 自動生成された catch ブロック
                e.printStackTrace();
            }
            saleTicket();
        }
        L.d("完了 残チケット:"+ticket);
    }
    private synchronized void saleTicket() {
        if(ticket > 0 ) {
            ticket--;
            L.d("残チケット枚数は"+ticket+"枚");
        }
    }
}

結果

ThreadSample#main:55 thread name:main thread id:1 gentest ::チケット販売開始
TicketBox#saleTicket:28 thread name:代理2 thread id:12 gentest ::残チケット枚数は4枚
TicketBox#saleTicket:28 thread name:代理3 thread id:13 gentest ::残チケット枚数は3枚
TicketBox#saleTicket:28 thread name:代理1 thread id:11 gentest ::残チケット枚数は2枚
TicketBox#saleTicket:28 thread name:代理2 thread id:12 gentest ::残チケット枚数は1枚
TicketBox#saleTicket:28 thread name:代理1 thread id:11 gentest ::残チケット枚数は0枚
TicketBox#run:23 thread name:代理2 thread id:12 gentest ::完了 残チケット:0
TicketBox#run:23 thread name:代理3 thread id:13 gentest ::完了 残チケット:0
TicketBox#run:23 thread name:代理1 thread id:11 gentest ::完了 残チケット:0

ステップ5 販売結果まとめ

github参考してください

結果

ThreadSample#main:85 thread name:main thread id:1 gentest ::チケット販売開始
TicketBox#saleTicket:52 thread name:代理2 thread id:12 gentest ::残チケット枚数は4枚
TicketBox#saleTicket:52 thread name:代理1 thread id:11 gentest ::残チケット枚数は3枚
TicketBox#saleTicket:52 thread name:代理3 thread id:13 gentest ::残チケット枚数は2枚
TicketBox#saleTicket:52 thread name:代理1 thread id:11 gentest ::残チケット枚数は1枚
TicketBox#saleTicket:52 thread name:代理2 thread id:12 gentest ::残チケット枚数は0枚
ThreadSample$1#taskDone:95 thread name:代理1 thread id:11 gentest ::お疲れ様です。代理1
ThreadSample$1#taskDone:95 thread name:代理2 thread id:12 gentest ::お疲れ様です。代理2
ThreadSample$1#taskDone:95 thread name:代理3 thread id:13 gentest ::お疲れ様です。代理3
ThreadSample$1#taskDone:100 thread name:代理3 thread id:13 gentest ::----------------全部完了 報告----------------------------
ThreadSample$2#sendResult:108 thread name:代理3 thread id:13 gentest ::全チケット数は:5
ThreadSample$2#sendResult:109 thread name:代理3 thread id:13 gentest ::残チケットは:0
ThreadSample$2#sendResult:110 thread name:代理3 thread id:13 gentest ::代理1販売結果:2
ThreadSample$2#sendResult:111 thread name:代理3 thread id:13 gentest ::代理2販売結果:2
ThreadSample$2#sendResult:112 thread name:代理3 thread id:13 gentest ::代理3販売結果:1

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2