サンプルから学ぶJava スレッド及びスレッドの同期

2009/02/17 14:06Update
TAGS: Java | Thread | Runnable | スレッド | 同期 | 優先度

スレッドとは何か、なぜスレッドは必要なのか、スレッドの同期は何などなど、サンプルから初心者向けにわかりやすく解説したいと思います。

Page:  <1|2>
Javaスレッド概要、サンプル
Javaスレッドの実装方法、状態、優先度、同期など

スレッドとは


スレッドはCPU利用の単位です。一つのスレッドはプロセスにある一つの処理を表します。複数のスレッド(マルチスレッド)が実行される時、JVMは優先度の高いスレッドの方にCPUを多く割り当て、早く終らせるようになります。

スレッド (コンピュータ) - Wikipedia

本文は
1、スレッドクラスの実装方法
2、スレッドの生成
3、スレッドの同期
4、スレッドのグループ化
などについて学びます。

サンプル


サンプルから見てみます。

「書店店員は本を売る」

1、仮に2人の店員は20冊の本を売るとします。
2、条件としては、すでにほかの店員に売り出された本を売ることはできません

処理対象:20冊の本
スレッド:
 スレッドA:店員A
 スレッドB:店員B

また、「売り出された本を売ることはできない」ことは、スレッドの同期を取る必要があると考えられます。


■ファイルリスト:
Book.java    本クラス
SellBookRunnable.java    「本を売る」クラス。スレッドの実装方法1
SellBookThread.java    「本を売る」クラス。スレッドの実装方法2
CallSellBook.java    「スレッドの生成」クラス

SellBookRunnable.javaとSellBookThread.java両方を実装する必要はありません、どちらの実装を使うか選べればいいのだと思います。

Book.java
public class Book {
    private String name;
    private boolean sold = false;

    public Book(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isSold() {
        return sold;
    }

    public void setSold(boolean sold) {
        this.sold = sold;
    }
}



SellBookRunnable.java
import java.util.List;

//Runnableインタフェース実装
public class SellBookRunnable implements Runnable {
    private String saleMan;    //店員
    private List<Book> bookList;    //売る対象となる本のリスト

    public SellBookRunnable(String saleMan, List<Book> bookList) {
        this.saleMan = saleMan;
        this.bookList = bookList;
    }

    public void run() {
        for (int i = 0; i < bookList.size(); i++) {
            Book book = bookList.get(i);
            sellBook(book);
        }
    }

    /**
     * 本を売る
     * 
     * @param book Book
     */
    private void sellBook(Book book) {
        //synchronizedを利用してスレッドの同期を取ります。synchronized (book)でbookは他の店員に取られないように制御します。
        synchronized (book) {
            if (book.isSold()) {    //既に売った場合
                return;
            } else {
                try {
                    //他のスレッドに実行されるチャンスを与えるため、0.5秒をあけます「本を取った時点から売ったまでの時間」。
                    Thread.sleep(500);
                } catch (Exception e) {
                }
                
                //売り出したとのフラグを設定します
                book.setSold(true);
                //売りましたよ
                System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
                        + book.isSold() + ". by "
                        + Thread.currentThread().getName());

            }
        }
    }
}


SellBookThread.java
import java.util.List;

public class SellBookThread extends Thread {
    private String saleMan;
    private List<Book> bookList;

    public SellBookThread(String saleMan, List<Book> bookList) {
        this.saleMan = saleMan;
        this.bookList = bookList;
    }

    public void run() {
        for (int i = 0; i < bookList.size(); i++) {
            Book book = bookList.get(i);
            sellBook(book);
        }
    }

    /**
     * 本を売る
     * 
     * @param book Book
     */
    private void sellBook(Book book) {
        //synchronizedを利用してスレッドの同期を取ります。synchronized (book)でbookは他の店員に取られないように制御します。
        synchronized (book) {
            if (book.isSold()) {    //既に売った場合
                return;
            } else {
                try {
                    //他のスレッドに実行されるチャンスを与えるため、0.5秒をあけます「本を取った時点から売ったまでの時間」。
                    Thread.sleep(500);
                } catch (Exception e) {
                }
                
                //売り出したとのフラグを設定します
                book.setSold(true);
                //売りましたよ
                System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
                        + book.isSold() + ". by "
                        + Thread.currentThread().getName());

            }
        }
    }
}


CallSellBook.java
import java.util.ArrayList;
import java.util.List;

//スレッドの生成、実行
public class CallSellBook {

    /**
     * マルチスレッドで「本を売る」ことをシミュレーションします
     */
    public static void main(String[] args) {
        //方法1
        callSellBookThread();

        //or
        
        //方法2
        //callSellBookRunnable();
    }
    
    //本を売る
    //SellBookThread(Threadクラスの実装)を利用します
    public static void callSellBookThread() {
        List <Book>bookList = getBookListForSale();    //売る対象となる本リスト
        
        //店員SaleMan1
        Thread t1 = new SellBookThread("SaleMan1", bookList);
        //店員SaleMan2
        Thread t2 = new SellBookThread("SaleMan2", bookList);

        //店員SaleMan1:「本を売る」処理開始
        t1.start();
        //店員SaleMan2:「本を売る」処理開始
        t2.start();
    }
    
    
    //本を売る
    //SellBookRunnable(Runnableインタフェースの実装)を利用します
    public static void callSellBookRunnable() {
        List <Book>bookList = getBookListForSale();    //売る対象となる本リスト
        
        //店員SaleMan1
        Thread t1 = new Thread(new SellBookRunnable("SaleMan1", bookList));
        //店員SaleMan2
        Thread t2 = new Thread(new SellBookRunnable("SaleMan2", bookList));

        //店員SaleMan1:「本を売る」処理開始
        t1.start();
        //店員SaleMan2:「本を売る」処理開始
        t2.start();
    }

    //売る対象となる本リスト
    public static List<Book> getBookListForSale() {
        List <Book>bookList = new ArrayList();
        for (int i = 0; i < 20; i++) {
            Book book = new Book("Book" + i);
            bookList.add(book);
        }
        
        return bookList;
    }
}


■実行結果(CallSellBook):

[SaleMan1]Book0 sold out:true. by Thread-0
[SaleMan2]Book1 sold out:true. by Thread-1
[SaleMan2]Book2 sold out:true. by Thread-1
[SaleMan2]Book3 sold out:true. by Thread-1
[SaleMan2]Book4 sold out:true. by Thread-1
[SaleMan2]Book5 sold out:true. by Thread-1
[SaleMan1]Book6 sold out:true. by Thread-0
[SaleMan1]Book7 sold out:true. by Thread-0
[SaleMan1]Book8 sold out:true. by Thread-0
[SaleMan1]Book9 sold out:true. by Thread-0
[SaleMan1]Book10 sold out:true. by Thread-0
[SaleMan1]Book11 sold out:true. by Thread-0
[SaleMan2]Book12 sold out:true. by Thread-1
[SaleMan2]Book13 sold out:true. by Thread-1
[SaleMan2]Book14 sold out:true. by Thread-1
[SaleMan2]Book15 sold out:true. by Thread-1
[SaleMan2]Book16 sold out:true. by Thread-1
[SaleMan2]Book17 sold out:true. by Thread-1
[SaleMan1]Book18 sold out:true. by Thread-0
[SaleMan1]Book19 sold out:true. by Thread-0

次のページ:解説(スレッドの生成、優先度、グループ化、同期など)
Page:  <1|2>

有关作者
Syboos.jp編集長AJavaやオープンソース情報の執筆、Webサイトの開発や運営全般の業務に携わる。

Sponsored Link


Comments

用户名 (required)

Email (will not be published) (required)

URL

Evaluation