Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java程序运行时在添加更多线程时保持不变,并产生不同的结果_Java_Multithreading_Concurrency_Locking_Java.util.concurrent - Fatal编程技术网

Java程序运行时在添加更多线程时保持不变,并产生不同的结果

Java程序运行时在添加更多线程时保持不变,并产生不同的结果,java,multithreading,concurrency,locking,java.util.concurrent,Java,Multithreading,Concurrency,Locking,Java.util.concurrent,以下是我的ConcurrentApp类代码,这是我问题的根源: class Processor implements Runnable { private int id; private Integer interaction; private Set<Integer> subset; private Set<Integer> y; private Object lock = new Object(); public D

以下是我的ConcurrentApp类代码,这是我问题的根源:

class Processor implements Runnable {

    private int id;
    private Integer interaction;
    private Set<Integer> subset;
    private Set<Integer> y;
    private Object lock = new Object();

    public DCP<BSN> dcp;



    public Processor(int id, Integer interaction, Set<Integer> subset, DCP<BSN> dcp, Set<Integer> y) {
        this.id = id;
        this.interaction = interaction;
        this.subset= subset;
        this.dcp = dcp;
        this.y = y;
    }

    public void run() {
        //System.out.println("Starting: " + this.id);
        if (this.y.contains(this.interaction)){
            this.subset.add(this.interaction);
            processRemoval(this.subset);
        }

        //System.out.println("Completed: " + this.id);
    }

    public void processRemoval(Set<Integer> collection){
        synchronized(Processor.lock) {
            for (Iterator<Integer> iter = this.y.iterator(); iter.hasNext(); ) {
                int element = iter.next();
                while(element != this.interaction){
                    element = iter.next();
                }
                this.dcp.increaseScore(collection);
                if (!collection.contains(this.interaction)) {
                    System.out.println(element + " WAS REMOVED by thread " + this.id);
                    iter.remove();
                }
            }
        }
    }

}


public class ConcurrentApp {

    public void multiRP (DCP<BSN> dcp, int threads) {

        ConcurrentHashMap<Integer,Boolean> x = new ConcurrentHashMap<Integer,Boolean>();
        ConcurrentHashMap<Integer,Boolean> z = new ConcurrentHashMap<Integer,Boolean>();
        Set<Integer> y = (Set<Integer>) Collections.newSetFromMap(x);
        y.addAll(dcp.PA);
        Set<Integer> zeta = (Set<Integer>) Collections.newSetFromMap(z);
        ExecutorService executor = Executors.newFixedThreadPool(threads);

        int i =1;
        while ((y.size() > i) && (i <= dcp.R)){
            for (Iterator<Integer> iterator = y.iterator(); iterator.hasNext();){
                zeta.addAll(y);
                Integer interaction = iterator.next();
                zeta.remove(interaction);
                ArrayList<Set<Integer>> subsets = dcp.getSubsets(zeta, i);
                for (int j = 0; j< subsets.size(); j++){
                    executor.submit(new Processor(j, interaction, subsets.get(j), dcp, y)); 
                }
            }
            i++;
        }
        executor.shutdown();
        System.out.println("All tasks submitted");
        try {
            executor.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(y);
        dcp.PA = new ArrayList<Integer>(y);
        System.out.println("All tasks completed");
    }
}
其中,第一个数字对应于从我的列表中删除的整数(例如,“0已被线程2删除”表示值0已从主列表y中删除)。这个输出是有意义的,因为每个需要删除的值都被删除了一次,并给出了预期的结果[7,8],这应该是本例中仅有的两个未删除的值

但是,当我使用>1个线程运行代码时,会得到以下输出:

All tasks submitted
0 WAS REMOVED by thread 2
1 WAS REMOVED by thread 1
2 WAS REMOVED by thread 0
2 WAS REMOVED by thread 1
3 WAS REMOVED by thread 1
3 WAS REMOVED by thread 2
4 WAS REMOVED by thread 0
4 WAS REMOVED by thread 1
5 WAS REMOVED by thread 0
5 WAS REMOVED by thread 1
6 WAS REMOVED by thread 0
6 WAS REMOVED by thread 1
7 WAS REMOVED by thread 1
7 WAS REMOVED by thread 2
8 WAS REMOVED by thread 1
8 WAS REMOVED by thread 0
[]
All tasks completed
Program completed in :0 seconds
如您所见,在某些情况下,相同的值被多次删除,因为多个线程决定需要删除该值。另一个问题是,这也会通过给我一个[]而不是[7,8]来改变我的结果,因为出于某种原因,当我使用多个线程时,程序错误地决定需要从主列表y中删除7和8。我通过向锁定字段添加static修复了多线程删除的问题:

private static Object lock = new Object();
但是,现在我有一个问题,当我增加线程数时,运行时不会改变。添加static后使用threads>=1的输出如下:

All tasks submitted
0 WAS REMOVED by thread 1
1 WAS REMOVED by thread 1
2 WAS REMOVED by thread 1
3 WAS REMOVED by thread 0
4 WAS REMOVED by thread 1
5 WAS REMOVED by thread 0
6 WAS REMOVED by thread 0
[7, 8]
All tasks completed
Program completed in :22 seconds
线程的数量并没有改善运行时,但我得到了正确的结果。无论我使用1个线程还是多个线程,这个结果和运行时都是完全相同的

问题:在我看来,有两种可能的解决方案:

1) 移除锁上的static关键字,并找到执行移除的线程告诉其他线程跳过移除的值的方法

2) 保留static关键字,找出为什么我的程序在有更多可用线程时只使用1个线程

任何想法都非常感谢

(我的朋友,你真的必须学会至少发布一部分代码)

我的诊断是:您的程序在多线程中的行为相同,因为
processremovation
在处理整个集合之前正在与其余线程同步,所以难怪该集合仅由第一个线程处理

在这些情况下,通常的方法是在处理每个项目之前同步线程。因此,似乎应该将
synchronize
块移动到循环中


但是,在这种情况下,您正在修改循环中的集合,这可能会产生
ConcurrentModificationException
。为了避免这种情况,我建议您也用另一个
Set
的并发实现来代替使用
HashSet
。例如,
ConcurrentSkipListSet
CopyOnWriteArraySet
,您可以选择。

很难相信所有这些代码都与问题相关。你能试着把它简化成一个吗?@shmosel第一个代码块是解决这个问题所需要的主代码。我以前也发布过类似的代码,并且被告知还要包含第二个代码块,以使事情变得更简单。请关注第一个代码块,但当您需要了解第一个代码块中的某些函数/类时,请参考第二个代码块。我相信这是一个完整的示例,但是,由于运行代码所需的各种包和依赖关系,一个可验证的示例将需要更多的代码。我尝试移动
synchronize
关键字,但似乎什么也没做(我将其移动到for循环中,并尝试在
processremove
中的不同位置)。我也没有得到任何
ConcurrentModificationException
,因为我的多线程访问集都有
ConcurrentHashMap
private static Object lock = new Object();
All tasks submitted
0 WAS REMOVED by thread 1
1 WAS REMOVED by thread 1
2 WAS REMOVED by thread 1
3 WAS REMOVED by thread 0
4 WAS REMOVED by thread 1
5 WAS REMOVED by thread 0
6 WAS REMOVED by thread 0
[7, 8]
All tasks completed
Program completed in :22 seconds