0

以下のように、サービスクラスの1つを介してコンストラクターを介して、スレッドの1つのクラス変数を初期化しています。

ProcessMediaThread pThread = new ProcessMediaThread(listMediaPath, mediaType);
pThread.start();  

listMediaPathはオブジェクトです ProcessMediaThread クラス内: ArrayList<String>();

public class ProcessMediaThread extends Thread 
{
    private List<String> absoluteMediaPath= new ArrayList<String>();
    private String mediaType;
    public ProcessMediaThread(List<String> absoluteMediaPathList, String mediaType) 
    {
       this.absoluteMediaPath = absoluteMediaPathList;
       this.mediaType= mediaType;
    }

私のオーバーライドされたrun()方法:

@Override
public void run()
{   
    if(mediaType.equals(MediaType.PHOTO)) //<- mediaType value is retained..
    {       
        for(int i=0;i<absoluteMediaPath.size();i++) // <- here absoluteMediaPath is empty..!!
        {
         //... 
        }

私の友人の1人は、コンストラクターレベルで別のアプローチに従うことを提案しています:

this.absoluteMediaPath.addAll(absoluteMediaPathList);

働いた.. !!
問題が発生している正確な場所と何をしているのかを誰かが提案できますaddAll(Collection<? extends E> c);か?

4

1 に答える 1

3

を使用するaddAllと、リストの内容が 内の別のコレクションにコピーされますProcessMediaThread。つまり、外部からの変更は影響しません。たとえば、次のことを考慮してください。

ProcessMediaThread pThread = new ProcessMediaThread(listMediaPath, mediaType);
pThread.start(); 
listMediaPath.clear();

現在のコードでは、新しいスレッドに空のコレクションが表示される場合があります。または、データを含むコレクションが突然クリアされる場合があります。良い状況ではありません。さらに、ArrayListスレッドセーフではないため、あるスレッドで変更して別のスレッドで読み取ると、問題が発生する可能性があります。

( を使用して)プライベートコピーを作成する場合、スレッドが使用しているのと同じコレクションには影響しないため、上記の 3 行目の は効果がありません。addAllclear()

その他のいくつかのポイント:

  • Runnableを拡張するのではなく、個別に実装することをお勧めしますThread。次に、 your のインスタンスをコンストラクターに渡すことができRunnableますThread。これにより、「新しいスレッドでタスクを実行するメカニズム」と「実行されるタスク」をより適切に分離できます。
  • ループ内での値が実際に必要iでない限り、以下を使用できます。

    for (String mediaPath : absoluteMediaPath) {
        ...
    }
    
  • 呼び出しに代わる方法addAllは、コンストラクターを使用して、コンストラクターでコレクションのみを初期化することArrayList(Collection)です。

したがって、これらすべてをまとめて、クラスを次のように変更します。

public class MediaProcessor implements Runnable {
    private final List<String> absoluteMediaPath;
    private final String mediaType;

    public MediaProcessor(List<String> absoluteMediaPathList, String mediaType) {
       this.absoluteMediaPath = new ArrayList(absoluteMediaPathList);
       this.mediaType = mediaType;
    }

    @Override
    public void run() {
        if (mediaType.equals(MediaType.PHOTO)) {
            for (String mediaPath : absoluteMediaPath) {
                ...
            }
        }
    }
}

...

Thread thread = new Thread(new MediaProcessor(listMediaPath, mediaType));
thread.start(); 
于 2013-06-20T05:46:33.930 に答える