Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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_Thread Safety_Concurrenthashmap - Fatal编程技术网

Java:测试服务的并发性

Java:测试服务的并发性,java,multithreading,concurrency,thread-safety,concurrenthashmap,Java,Multithreading,Concurrency,Thread Safety,Concurrenthashmap,我有一个服务类,其中包含一个方法,可以将学生添加到部分。现在,每个部分都有一组与之相关联的学生 此外,还有一个Map定义了两者之间的关系 使用addStudent方法,服务看起来像这样: public class MembershipService { private final Map<Section, Set<Student>> studentsBySection = new HashMap<>(); public void addStudentTo

我有一个服务类,其中包含一个方法,可以将
学生
添加到
部分
。现在,每个
部分
都有一组与之相关联的
学生

此外,还有一个
Map
定义了两者之间的关系

使用
addStudent
方法,服务看起来像这样:

public class MembershipService {

private final Map<Section, Set<Student>> studentsBySection = new HashMap<>();


public void addStudentToSection(Student student, Section sec) {

 Set<Student> students = studentsBySection.get(sec);
    if (students == null) {
        students = new HashSet<>();
        studentsBySection.put(sec, students);
    }
    students.add(student);

}
//  ..... also containing helper method : getStudents(Section s)
}

学生2

  public class Student2 implements Runnable{

Services services;

public Student2(Services ser) {
    this.services =  ser;
    new Thread(this, "Student 2").start();
}



@Override
public void run() {
    final Student JOHN = new Student("john");


    services.getMembershipService().addStudentToSection(JOHN,services.getSection());;

    try {
        System.out.println("Student 2 sleeping");
        Thread.sleep(100);
    } catch (Exception e) {
        System.out.println(e);
    }

}
}

Tester.java

public static void main(String[] args) {
    final Services services = ServiceFactory.createServices();
    final Section A = new Section("A");
    services.createSection(A);

    Student1 one = new Student1(services);
    Student2 two = new Student2(services);

}
我如何证明我的情况


注意:这不是关于ConcurrentHashMap在java中如何工作的问题,也不是关于多线程的问题。我知道这一点。我只是无法使它与我的需求保持一致。

首先,
ConcurrentModificationException
仅由迭代器引发,而不是由bu
put()/get()

该类的所有“集合”视图返回的迭代器 方法“*是快速失效的:如果地图在结构上被修改 在*之后的任何时间,以任何方式创建迭代器,除了 通过迭代器自己的*remove方法,迭代器 将抛出一个*{@link ConcurrentModificationException}。因此,在 面对并发*修改,迭代器会快速失败,并且 干净,而不是冒险*任意、不确定的行为 在未来一个不确定的时间

要证明
Hashmap
是非线程安全的,最好的方法是将
部分
类更改为从
hashCode()
方法返回常量(以加快失败速度)


然后,您只需创建1000个不同的
Section
对象,并尝试调用您的服务,将学生映射到多个线程中的Section。基本上,当你把学生映射到各个部分时,地图上的大小将与部分的数量不匹配,它将小于不同部分的数量

首先,
ConcurrentModificationException
仅由迭代器引发,而不是由bu
put()/get()

该类的所有“集合”视图返回的迭代器 方法“*是快速失效的:如果地图在结构上被修改 在*之后的任何时间,以任何方式创建迭代器,除了 通过迭代器自己的*remove方法,迭代器 将抛出一个*{@link ConcurrentModificationException}。因此,在 面对并发*修改,迭代器会快速失败,并且 干净,而不是冒险*任意、不确定的行为 在未来一个不确定的时间

要证明
Hashmap
是非线程安全的,最好的方法是将
部分
类更改为从
hashCode()
方法返回常量(以加快失败速度)


然后,您只需创建1000个不同的
Section
对象,并尝试调用您的服务,将学生映射到多个线程中的Section。基本上,当你把学生映射到各个部分时,地图上的大小将与部分的数量不匹配,它将小于不同部分的数量

HashMap和ConcurrentHashMap在多线程环境中工作相同的原因是输入较少。 我同时放置和读取200个键值对

只需在代码中将ConcurrentHashMap替换为HashMap,您将获得concurrentModificationException

ConcurrentHashMap实现:

package com.java.ConcurrentHashMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo {


    private  final ConcurrentHashMap<Section,Set<Student>> studentsBySection = new ConcurrentHashMap<>();

    public  void addStudentToSection(Student student, Section sec) {
//System.out.println(Thread.currentThread().getName());
         Set<Student> students = studentsBySection.get(sec);
            if (students == null) {
                students = new HashSet<>();
                studentsBySection.putIfAbsent(sec, students);
            }
            students.add(student);

        }




      public static void main(String[] args) {
          ConcurrentHashMapDemo ob = new ConcurrentHashMapDemo();



          Thread t1 = new Thread(ob.new WriteThreasOne());
          t1.setName("one");

          Thread t3 = new Thread(ob.new WriteThreasTwo());
          t3.setName("three");
          Thread t2= new Thread(ob.new ReadThread());
          t2.setName("two");
          t1.start();
          t2.start();
          t3.start();
      }
      class WriteThreasOne implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");

            for(int i=0;i<100;i++) {
                addStudentToSection(new Student("alex"+i),A);
            }




        }
      }
      class WriteThreasTwo implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");
            for(int i=1;i<100;i++) {
                addStudentToSection(new Student("sam"+i),A);
            }


        }
      }  
      class ReadThread implements Runnable {
        @Override
        public void run() {
            //System.out.println(Thread.currentThread().getName());

           Iterator<Section> ite = studentsBySection.keySet().iterator();
           while(ite.hasNext()){
               Section key = ite.next();
               System.out.println(key+" : " + studentsBySection.get(key));
          }
        }
      }   
}
package com.java.ConcurrentHashMap;

public class Section {

    public Section(String sectionName) {
        this.sectionName = sectionName;
    }

    private String sectionName;



    public String getSectionName() {
        return sectionName;
    }

    public void setSectionName(String sectionName) {
        this.sectionName = sectionName;
    }

    @Override
    public String toString() {
        return "Section [sectionName=" + sectionName + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((sectionName == null) ? 0 : sectionName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Section other = (Section) obj;
        if (sectionName == null) {
            if (other.sectionName != null)
                return false;
        } else if (!sectionName.equals(other.sectionName))
            return false;
        return true;
    }



}
package com.java.ConcurrentHashMap;

public class Student {



    private String studName;

    public Student(String studName) {

        this.studName = studName;
    }

    public String getStudName() {
        return studName;
    }

    public void setStudName(String studName) {
        this.studName = studName;
    }

    @Override
    public String toString() {
        return "Student [ studName=" + studName + "]";
    }

}
学生班:

package com.java.ConcurrentHashMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo {


    private  final ConcurrentHashMap<Section,Set<Student>> studentsBySection = new ConcurrentHashMap<>();

    public  void addStudentToSection(Student student, Section sec) {
//System.out.println(Thread.currentThread().getName());
         Set<Student> students = studentsBySection.get(sec);
            if (students == null) {
                students = new HashSet<>();
                studentsBySection.putIfAbsent(sec, students);
            }
            students.add(student);

        }




      public static void main(String[] args) {
          ConcurrentHashMapDemo ob = new ConcurrentHashMapDemo();



          Thread t1 = new Thread(ob.new WriteThreasOne());
          t1.setName("one");

          Thread t3 = new Thread(ob.new WriteThreasTwo());
          t3.setName("three");
          Thread t2= new Thread(ob.new ReadThread());
          t2.setName("two");
          t1.start();
          t2.start();
          t3.start();
      }
      class WriteThreasOne implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");

            for(int i=0;i<100;i++) {
                addStudentToSection(new Student("alex"+i),A);
            }




        }
      }
      class WriteThreasTwo implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");
            for(int i=1;i<100;i++) {
                addStudentToSection(new Student("sam"+i),A);
            }


        }
      }  
      class ReadThread implements Runnable {
        @Override
        public void run() {
            //System.out.println(Thread.currentThread().getName());

           Iterator<Section> ite = studentsBySection.keySet().iterator();
           while(ite.hasNext()){
               Section key = ite.next();
               System.out.println(key+" : " + studentsBySection.get(key));
          }
        }
      }   
}
package com.java.ConcurrentHashMap;

public class Section {

    public Section(String sectionName) {
        this.sectionName = sectionName;
    }

    private String sectionName;



    public String getSectionName() {
        return sectionName;
    }

    public void setSectionName(String sectionName) {
        this.sectionName = sectionName;
    }

    @Override
    public String toString() {
        return "Section [sectionName=" + sectionName + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((sectionName == null) ? 0 : sectionName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Section other = (Section) obj;
        if (sectionName == null) {
            if (other.sectionName != null)
                return false;
        } else if (!sectionName.equals(other.sectionName))
            return false;
        return true;
    }



}
package com.java.ConcurrentHashMap;

public class Student {



    private String studName;

    public Student(String studName) {

        this.studName = studName;
    }

    public String getStudName() {
        return studName;
    }

    public void setStudName(String studName) {
        this.studName = studName;
    }

    @Override
    public String toString() {
        return "Student [ studName=" + studName + "]";
    }

}

HashMap和ConcurrentHashMap在多线程环境中工作相同的原因是输入较少。 我同时放置和读取200个键值对

只需在代码中将ConcurrentHashMap替换为HashMap,您将获得concurrentModificationException

ConcurrentHashMap实现:

package com.java.ConcurrentHashMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo {


    private  final ConcurrentHashMap<Section,Set<Student>> studentsBySection = new ConcurrentHashMap<>();

    public  void addStudentToSection(Student student, Section sec) {
//System.out.println(Thread.currentThread().getName());
         Set<Student> students = studentsBySection.get(sec);
            if (students == null) {
                students = new HashSet<>();
                studentsBySection.putIfAbsent(sec, students);
            }
            students.add(student);

        }




      public static void main(String[] args) {
          ConcurrentHashMapDemo ob = new ConcurrentHashMapDemo();



          Thread t1 = new Thread(ob.new WriteThreasOne());
          t1.setName("one");

          Thread t3 = new Thread(ob.new WriteThreasTwo());
          t3.setName("three");
          Thread t2= new Thread(ob.new ReadThread());
          t2.setName("two");
          t1.start();
          t2.start();
          t3.start();
      }
      class WriteThreasOne implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");

            for(int i=0;i<100;i++) {
                addStudentToSection(new Student("alex"+i),A);
            }




        }
      }
      class WriteThreasTwo implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");
            for(int i=1;i<100;i++) {
                addStudentToSection(new Student("sam"+i),A);
            }


        }
      }  
      class ReadThread implements Runnable {
        @Override
        public void run() {
            //System.out.println(Thread.currentThread().getName());

           Iterator<Section> ite = studentsBySection.keySet().iterator();
           while(ite.hasNext()){
               Section key = ite.next();
               System.out.println(key+" : " + studentsBySection.get(key));
          }
        }
      }   
}
package com.java.ConcurrentHashMap;

public class Section {

    public Section(String sectionName) {
        this.sectionName = sectionName;
    }

    private String sectionName;



    public String getSectionName() {
        return sectionName;
    }

    public void setSectionName(String sectionName) {
        this.sectionName = sectionName;
    }

    @Override
    public String toString() {
        return "Section [sectionName=" + sectionName + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((sectionName == null) ? 0 : sectionName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Section other = (Section) obj;
        if (sectionName == null) {
            if (other.sectionName != null)
                return false;
        } else if (!sectionName.equals(other.sectionName))
            return false;
        return true;
    }



}
package com.java.ConcurrentHashMap;

public class Student {



    private String studName;

    public Student(String studName) {

        this.studName = studName;
    }

    public String getStudName() {
        return studName;
    }

    public void setStudName(String studName) {
        this.studName = studName;
    }

    @Override
    public String toString() {
        return "Student [ studName=" + studName + "]";
    }

}
学生班:

package com.java.ConcurrentHashMap;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapDemo {


    private  final ConcurrentHashMap<Section,Set<Student>> studentsBySection = new ConcurrentHashMap<>();

    public  void addStudentToSection(Student student, Section sec) {
//System.out.println(Thread.currentThread().getName());
         Set<Student> students = studentsBySection.get(sec);
            if (students == null) {
                students = new HashSet<>();
                studentsBySection.putIfAbsent(sec, students);
            }
            students.add(student);

        }




      public static void main(String[] args) {
          ConcurrentHashMapDemo ob = new ConcurrentHashMapDemo();



          Thread t1 = new Thread(ob.new WriteThreasOne());
          t1.setName("one");

          Thread t3 = new Thread(ob.new WriteThreasTwo());
          t3.setName("three");
          Thread t2= new Thread(ob.new ReadThread());
          t2.setName("two");
          t1.start();
          t2.start();
          t3.start();
      }
      class WriteThreasOne implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");

            for(int i=0;i<100;i++) {
                addStudentToSection(new Student("alex"+i),A);
            }




        }
      }
      class WriteThreasTwo implements Runnable {
        @Override
        public void run() {


            final Section A = new Section("A");
            for(int i=1;i<100;i++) {
                addStudentToSection(new Student("sam"+i),A);
            }


        }
      }  
      class ReadThread implements Runnable {
        @Override
        public void run() {
            //System.out.println(Thread.currentThread().getName());

           Iterator<Section> ite = studentsBySection.keySet().iterator();
           while(ite.hasNext()){
               Section key = ite.next();
               System.out.println(key+" : " + studentsBySection.get(key));
          }
        }
      }   
}
package com.java.ConcurrentHashMap;

public class Section {

    public Section(String sectionName) {
        this.sectionName = sectionName;
    }

    private String sectionName;



    public String getSectionName() {
        return sectionName;
    }

    public void setSectionName(String sectionName) {
        this.sectionName = sectionName;
    }

    @Override
    public String toString() {
        return "Section [sectionName=" + sectionName + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((sectionName == null) ? 0 : sectionName.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Section other = (Section) obj;
        if (sectionName == null) {
            if (other.sectionName != null)
                return false;
        } else if (!sectionName.equals(other.sectionName))
            return false;
        return true;
    }



}
package com.java.ConcurrentHashMap;

public class Student {



    private String studName;

    public Student(String studName) {

        this.studName = studName;
    }

    public String getStudName() {
        return studName;
    }

    public void setStudName(String studName) {
        this.studName = studName;
    }

    @Override
    public String toString() {
        return "Student [ studName=" + studName + "]";
    }

}

由于哈希代码不变,创建1000个不同的节可能位于同一个bucket位置。无法理解在这种情况下映射将如何工作,或者大小将如何比较?HashMap中的Bucket是一种链表。因此,当多个线程开始向
HashMap
添加元素时,这些元素将被添加到一个不安全的列表中。这种使用常量哈希代码的黑客攻击会增加在
哈希映射中添加元素时出现错误行为的可能性。基本上,在线程不安全的情况下,
HashMap
在多个线程中添加几个元素后,map的最终大小将小于添加元素的数量。您可以查看此问题的答案以了解一个想法:既然hashcode是常量,那么ConcurrentHashMap的情况不也是这样吗?
ConcurrentHashMap
会锁定存储桶
put()
因此它可以正常工作,尽管性能会比使用返回不同值的hashCode实现差。由于hashCode是常量,因此创建1000个不同的节可能位于同一个存储桶位置。无法理解在这种情况下映射将如何工作,或者大小将如何比较?HashMap中的Bucket是一种链表。因此,当多个线程开始向
HashMap
添加元素时,这些元素将被添加到一个不安全的列表中。这种使用常量哈希代码的黑客攻击会增加在
哈希映射中添加元素时出现错误行为的可能性。基本上,在线程不安全的情况下,
HashMap
在多个线程中添加几个元素后,map的最终大小将小于添加元素的数量。您可以查看此问题的答案以了解一个想法:既然hashcode是常量,那么ConcurrentHashMap的情况不也是这样吗?
ConcurrentHashMap
会锁定存储桶
put()
因此它可以正常工作,尽管性能会比返回不同值的hashCode实现差。我已经根据