0

我正在通过我的服务类之一通过其构造函数初始化我的线程之一的类变量,如下所示:

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

其中listMediaPath是一个ArrayList<String>();对象。
ProcessMediaThread 类内部:

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..!!
        {
         //... 
        }

我的一位朋友建议我在构造函数级别采用不同的方法:

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它不是线程安全的,因此在一个线程中修改它并在另一个线程中读取它很可能会导致问题。

当您创建私有副本(使用addAll)时,clear()上面第三行的 将不起作用,因为它不会影响线程正在使用的同一个集合。

其他几点:

  • 我建议您Runnable单独实现而不是扩展Thread. 然后,您可以将您的实例传递RunnableThread构造函数;这可以更好地分离“在新线程上运行任务的机制”和“要运行的任务”。
  • 除非您确实需要循环中的值,否则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 回答