1

クラス UnSafeTask を作成しました。

package com.threads;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class UnsafeTask implements Runnable {
    private Date startDate;

    @Override
    public void run() {
        startDate = new Date();
        System.out.printf("Starting Thread: %s : %s\n", Thread.currentThread().getId(), startDate);
        try {
            TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Thread Finished: %s : %s\n", Thread.currentThread().getId(), startDate);
    }    
}

以下のようにコアクラスで使用しました。

package com.threads;

import java.util.concurrent.TimeUnit;

public class Core {

    public static void main(String[] args) {
        UnsafeTask task = new UnsafeTask();

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(task);
            thread.start();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

結果は期待どおりです (変数はスレッドによって共有されます)。匿名の実行可能なクラスを使用するために次のようにコアをリファクタリングしたとき:

package com.threads;

import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Core {

    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(new Runnable() {
                Date startDate = new Date();

                @Override
                public void run() {
                    startDate = new Date();
                    System.out.printf("Starting Thread: %s : %s\n", Thread.currentThread().getId(), startDate);
                    try {
                        TimeUnit.SECONDS.sleep((int) Math.rint(Math.random() * 10));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.printf("Thread Finished: %s : %s\n", Thread.currentThread().getId(), startDate);    
                }    
            });
            thread.start();
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

これで、変数 (startDate) はスレッド セーフになりました。この場合、変数がスレッドセーフなのはなぜですか? 前もって感謝します。

4

4 に答える 4

3

最初の例では、Runnable の 1 つのインスタンスがあります (すべてのスレッドで共有されます)。2 番目の例では、Runnable のインスタンスが 10 個あり、スレッドごとに 1 つのインスタンスがあります (共有がないため、スレッドセーフです)。

于 2012-11-30T03:17:22.910 に答える
1

スレッド セーフは、クラスに名前があるかどうかに依存しません。最初のケースでは、名前付きクラスのインスタンスをすべてのスレッドで共有します。2 番目の匿名クラスを使用して、まったく同じことを簡単に行うことができます。

finalさらに、匿名クラスのインスタンス間で外側のスコープで宣言された変数を共有できます。変数は final でなければなりませんが、そのインスタンスがimmutableになるという意味ではありません。そのような場合、無名クラスは確実に非スレッドセーフになります。

したがって、タイトルの質問からの答えは、「いいえ、すべての匿名クラスがスレッドセーフであるとは限りません」です。名前が付けられているかどうかに関係なく、スレッド セーフを念頭に置いてクラスを明示的に設計する必要があります。

于 2012-11-30T03:21:52.897 に答える
0

2 番目の例は、最初の例をわずかに変更したものと同じであることに注意してください。

public static void main(String[] args) {

    for (int i = 0; i < 10; i++) {
        // Task object instantiation now inside for loop:
        UnsafeTask task = new UnsafeTask();   
        Thread thread = new Thread(task);
于 2013-05-06T21:17:57.107 に答える
0

クラスが匿名であるかどうかは、スレッド セーフとは無関係です。

匿名クラスは通常のクラスと同じですが、ソースが独自の.javaファイルに存在しないこと (およびその他のいくつかの非常に小さな点) が異なります。

于 2012-11-30T03:26:54.993 に答える