0

コードスニペットを実装してマルチスレッドを学習しようとしています。問題は、4 つのスレッド (それぞれ 13) を使用して 4 つのリストにカード (52) を配布することです。以下のコードでより良い解決策または修正を提案してください。

これはマルチスレッドの練習用なので、命名規則やジェネリックについてはあまり強調していません (申し訳ありません)。

import java.util.LinkedList;
import java.util.List;

public class CardsDivideIntoFour {
    static final int Max = 52;
    static int val = 0;
    static Object ox = new Object();
    static List list1 = new LinkedList();
    static List list2 = new LinkedList();
    static List list3 = new LinkedList();
    static List list4 = new LinkedList();

    public static void main(String[] args) {

        Thread t1 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    if (val >= Max) {
                        break;
                    }
                    synchronized (ox) {
                        list1.add(++val);
                        System.out.println("a>  " + val);
                        ox.notifyAll();
                        try {
                            if (val >= Max) {
                                // System.out.println("t1 run finished");
                                // Thread.currentThread().interrupt();
                                break;
                            }
                            Thread.sleep(1000);
                            ox.wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }
                // Unreachable code
                // System.out.println("t1 run finished");

            }
        });

        Thread t2 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    if (val >= Max) {
                        break;
                    }
                    synchronized (ox) {
                        list2.add(++val);
                        System.out.println("b>  " + val);
                        ox.notifyAll();
                        try {
                            if (val >= Max) {
                                break;
                            }
                            Thread.sleep(1000);
                            ox.wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        });

        Thread t3 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    if (val >= Max) {
                        break;
                    }
                    synchronized (ox) {
                        list3.add(++val);
                        System.out.println("c> " + val);
                        ox.notifyAll();
                        try {
                            if (val >= Max) {
                                break;
                            }
                            Thread.sleep(1000);
                            ox.wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        });

        Thread t4 = new Thread(new Runnable() {
            public void run() {
                while (true) {
                    if (val >= Max) {
                        break;
                    }
                    synchronized (ox) {
                        list4.add(++val);
                        System.out.println("d> " + val);
                        ox.notifyAll();
                        try {
                            if (val >= Max) {
                                break;
                            }
                            Thread.sleep(1000);
                            ox.wait();
                        } catch (InterruptedException e) {
                        }
                    }
                }
            }
        });

        t1.start();
        t2.start();
        t3.start();
        t4.start();

        try {
            t1.join();
            t2.join();
            t3.join();
            t4.join();
        } catch (Exception e) {
        }

        System.out.print("List1 has > ");
        for (Object o : list1) {
            System.out.print((Integer) o + ",");
        }

        System.out.println("");
        System.out.print("List2 has > ");
        for (Object o : list2) {
            System.out.print((Integer) o + ",");
        }

        System.out.println("");
        System.out.print("List3 has > ");
        for (Object o : list3) {
            System.out.print((Integer) o + ",");
        }

        System.out.println("");
        System.out.print("List4 has > ");
        for (Object o : list4) {
            System.out.print((Integer) o + ",");
        }
    }
}
4

2 に答える 2

0

なぜ車輪の再発明をするのですか?新しいJavaSE7は、Fork\Join frameworkこのジョブを同時に実行するを提供します。

于 2013-03-20T21:37:29.717 に答える
0

現在のスレッドの順番を示すフィールドを追加するのはどうですか?

static int turn = 0;

コードを見てください。

同期の詳細

スレッド同期には 3 つの部分があります。

1) まず、スレッドは でロックを取得する必要がありますsynchronized (ox)。スレッドは、ホルダー スレッドがロックを解放するまでブロッキング状態にあり、スレッドはロックを取得しようとします。ロックの取得に再度失敗すると、再びブロッキング状態になります。

2) スレッドがロックを取得して のブロックに入る場合、synchronized最初に、実際にロックを取得できるかどうか、または何らかの操作が行われるのを待機できるかどうかを判断する必要があります。したがって、ターンがスレッドのターンであるかどうかを確認するループがあります。そうでない場合、スレッドは待機状態になり、「タスクを完了する順番があるスレッドを待つ必要があります」と言います。スレッドは、別のスレッドが で呼び起こすまで、待機状態のままになりnotifyAllます。次に、ジョブを実行できるかどうかを再判断し、実行できない場合は、再び待機状態になります。そうでなければ、それはその仕事をします。

3) 最後に、スレッドは、そのタスクの終了後に使用して、待機中の他のスレッドをウェイクアップすることを忘れません。notfiyAll忘れると、他のスレッドは永久に待機状態になります。この状態はデッドロックと呼ばれ、プログラムがハングアップする可能性があります。

于 2013-03-20T21:52:12.453 に答える