发出从线程访问类变量的问题

时间:2010-06-14 07:40:55

标签: java multithreading

以下代码旨在将产品对象的arraylist作为输入,为每个产品旋转线程(并将产品添加到arraylist'产品'),检查产品图像(product.imageURL)可用性,删除产品没有图像(从arraylist'产品中删除产品'),并返回带有图像的产品的arraylist。

package com.catgen.thread;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.catgen.Product;
import com.catgen.Utils;

public class ProductFilterThread extends Thread{

    private Product product;
    private List<Product> products = new ArrayList<Product>();

    public ProductFilterThread(){
    }

    public ProductFilterThread(Product product){
        this.product = product;
    }

    public synchronized void addProduct(Product product){
         System.out.println("Before add: "+getProducts().size());
         getProducts().add(product);
         System.out.println("After add: "+getProducts().size());
    }

    public synchronized void removeProduct(Product product){
         System.out.println("Before rem: "+getProducts().size());
         getProducts().remove(product);
         System.out.println("After rem: "+getProducts().size());
    }

    public synchronized List<Product> getProducts(){
        return this.products;
    }

    public synchronized void setProducts(List<Product> products){
        this.products = products;
    }

    public void run(){
        boolean imageExists = Utils.fileExists(this.product.ImageURL);
        if(!imageExists){
            System.out.println(this.product.ImageURL);
            removeProduct(this.product);
        }
    }

    public List<Product> getProductsWithImageOnly(List<Product> products){
        ProductFilterThread pft = null;
        try{
            List<ProductFilterThread> threads = new ArrayList<ProductFilterThread>();
            for(Product product: products){
                pft = new ProductFilterThread(product);
                addProduct(product);
                pft.start();
                threads.add(pft);
            }
            Iterator<ProductFilterThread> threadsIter = threads.iterator();
            while(threadsIter.hasNext()){
                ProductFilterThread thread = threadsIter.next();
                thread.join();
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("Total returned products = "+getProducts().size());
        return getProducts();
    }
}

致电声明:

displayProducts = new ProductFilterThread().getProductsWithImageOnly(displayProducts);

这里,当从getProductsWithImageOnly()中调用addProduct(product)时,getProducts()返回产品列表,但当线程调用removeProduct()方法时,情况并非如此(不返回任何产品),因此,没有图像的产品永远不会被删除。因此,无论所包含的产品是否有图像,模块都会返回所有产品。

这里有什么问题?

提前致谢。 詹姆斯。

2 个答案:

答案 0 :(得分:0)

你在循环中每次迭代创建一个新的ProductFilterThread

new ProductFilterThread(product);

每个ProductFilterThread都有自己的

private List<Product> products = new ArrayList<Product>();

所以当你使用run方法时,

removeProduct(this.product);

您要从自己的products实例中删除该产品。

我建议你以不同的方式设计它,或许给出线程应该使用的产品列表,作为ProductFilterThread的参数:

private List<Product> products;

public ProductFilterThread(List<Product> products) {
    this.products = products;
}

但我必须说,在使用像这样的多个线程时你应该仔细考虑。您需要仔细同步对数据结构的访问。

答案 1 :(得分:0)

如果您希望所有Filter Threads共享products列表,那么您必须将其设置为静态。字段为confined to a single thread

另一个评论 - 也许你应该重写products的getter / setter方法来导出一个不可修改的列表并读取新创建的列表中的输入。否则,这可能是这种多线程设计中多次头痛的原因(只是想象另一个线程“获取”列表并在过滤处于活动状态时对其进行修改。)

相关问题