Java Programming 2015 – 11

スレッドを使う

Javaでは、標準機能としてスレッドが組み込まれています。

スレッドを使う

スレッドを使うには、 java.jang.Threadクラスを継承する方法と、 Java.lang.Runnableインターフェースを実装する方法があります。

Threadクラスを継承する

Threadクラスを継承したスレッドのサンプルです。

package com.drjiro.thread;

/**
 * Threadクラスを継承したスレッドサンプル。
 * 
 * @author wada
 */
class TestThread1 extends Thread {
    /** 待ち時間 */
    private long time;

    /**
     * コンストラクタで待ち時間を設定する。
     * 
     * @param time  待ち時間
     */
    TestThread1(long time) {
        this.time = time;
    }

    /**
     * スレッド実行コードをrunメソッドに書く。
     */
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(getName() + ":" + i);
            try {
                // timeミリ秒スリープする。
                sleep(time);
            } catch (InterruptedException e) {
                // 何もしない。
            }
        }
    }

    /**
     * テスト用メイン。
     * 
     * @param args  今は使わない
     */
    public static void main(String[] args) {
        // TestThread1クラスのオブジェクトを作成する。
        TestThread1 thread1 = new TestThread1(100);
        TestThread1 thread2 = new TestThread1(200);

        // スレッド1を開始する。
        thread1.start();
        // スレッド2を開始する。
        thread2.start();
    }
}

Runnableインターフェースを使う

Runnableインターフェースを実装したスレッドのサンプルです。

package com.drjiro.thread;
class TestThread2 implements Runnable {
    /** 待ち時間 */
    private long time;

    TestThread2(long time) {
        this.time = time;
    }

    /**
     * スレッド実行コードをrunメソッドに書く。
     */
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try {
                // timeミリ秒スリープする。
                Thread.sleep(time);
            } catch (InterruptedException e) {
                // 何もしない。
            }
        }
    }

    public static void main(String[] args) {
        // TestThread2クラスのオブジェクトを作成する。
        TestThread2 thread = new TestThread2(100);
        // スレッドのオブジェクトを作成する。
        Thread thread1 = new Thread(thread);
        Thread thread2 = new Thread(thread);

        // スレッド1を開始する。
        thread1.start();
        // スレッド2を開始する。
        thread2.start();
    }
}

待ち合わせ

join()メソッドを使うと、スレッドを待ち合わせすることができます。

joinメソッドには、引数の異なる3つのメソッドがあります。
1. void join()
スレッドが終了するのを永久に待ちます。
2. void join(long millis),void join(long millis, int nanos)
指定した時間経過すれば処理を再開します。

package com.drjiro.thread;

class TestJoin1 extends Thread {
    /** 待ち時間 */
    private long time;

    TestJoin1(long time) {
        this.time = time;
    }

    /**
     * スレッド実行コードをrunメソッドに書く。
     */
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(getName() + ":" + i);
            try {
                // timeミリ秒スリープする。
                sleep(time);
            } catch (InterruptedException e) {
                // 何もしない。
            }
        }
    }

    public static void main(String[] args) {
        // TestThread1クラスのオブジェクトを作成する。
        TestJoin1 thread1 = new TestJoin1(100);

        // スレッド1を開始する。
        thread1.start();

        try {
            System.out.println("スレッドthread1の終了を待機します。");
            // スレッド1が終了するのを待つ
            thread1.join();
        } catch (InterruptedException e) {
            // 何もしない。
        }
        System.out.println("スレッド thread1 が終了しました。");
    }
}

##

スレッドを同期するには、 synchronizedブロック(またはsynchronizedメソッド)を使います。
クラスやインスタンスはそれぞれ「ロックフラグ」(lock,鍵)というものを持っています。
スレッドはsynchronizedブロックの開始時に指定したオブジェクトのロックを取得し終了時に解放します。

  1. synchronizedブロック (共有しているAccountクラスに適用する)
    java
    public synchronized void deposit(long amount) {
    synchronized(this) {
    balance += amount;
    }
    }
  2. “java
    public synchronized void deposit(long amount) {
    balance += amount;
    }
    “`
スレッドを同期されるサンプルです。

package com.drjiro.thread;
/*
 * 
 * 
 * Copyright (C) 2012 Trident College of Information Technology. All rights reserved.
 */

/**
 * スレッドの同期サンプル。
 * 
 * @author wada
 */
public class TestSynchronize1 extends Thread {
    /** 名前 */
    private String name;
    /** 口座 */
    private Account account;
    /** 待ち時間 */
    private long time;

    /**
     * コンストラクタで口座を設定する。
     * 
     * @param time
     *            待ち時間
     * @param name
     *            名前
     * @param account
     *            口座
     */
    public TestSynchronize1(long time, String name, Account account) {
        this.time = time;
        this.name = name;
        this.account = account;
    }

    /**
     * スレッド実行コードをrunメソッドに書く。
     */
    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            System.out.println(name + ":100円預け入れ");
            account.deposit(100);
            System.out.println("残高=" + account.getBalance());
            try {
                // timeミリ秒スリープする。
                sleep(time);
            } catch (InterruptedException e) {
                // 何もしない。
            }
        }
    }

    public static void main(String[] args) {
        Account account = new Account(1000);
        System.out.println("1000円預け入れ");

        // スレッドのオブジェクトを作成する。
        TestSynchronize1 thread1 = new TestSynchronize1(1000, "A", account);
        TestSynchronize1 thread2 = new TestSynchronize1(1000, "B", account);

        // スレッド1を開始する。
        thread1.start();
        // スレッド2を開始する。
        thread2.start();
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            System.out.println("待ち合わせ終了");
        }

        System.out.println("最終残高=" + account.getBalance());
    }
}

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください