哪些Java集合是同步的(线程安全的),哪些不是?

哪些Java集合是同步的(线程安全的),哪些不是?,java,collections,Java,Collections,哪些Java集合是同步的,哪些不是 示例:哈希集未同步您可以使用 Collections.synchronizedCollection(Collection<T> c) Collections.synchronizedCollection(集合c) []我猜集合API的每个实现都是在文档中编写的。简单回答:没有一个集合的实现是同步的,因为synchronized不是类属性,它只适用于方法和块 我猜,您想知道哪些实现是线程安全的,java集合框架中的哪些类可以在多线程环境中安全使用

哪些Java集合是同步的,哪些不是


示例:哈希集未同步

您可以使用

Collections.synchronizedCollection(Collection<T> c)
Collections.synchronizedCollection(集合c)

[]

我猜集合API的每个实现都是在文档中编写的。

简单回答:没有一个
集合的实现是同步的,因为
synchronized
不是类属性,它只适用于方法和块

我猜,您想知道哪些实现是线程安全的,java集合框架中的哪些类可以在多线程环境中安全使用


这些信息总是包含在javadoc中(-它不是线程安全的)

有三组集合

  • Java 1.0集合主要是遗留类。这包括哈希表、向量、堆栈。这些是同步的,但我不建议您使用它们。属性可能是一个例外,但我不会在多线程上下文中使用它
  • 1998年添加的Java 1.2集合在很大程度上取代了这些集合,这些集合不同步,但可以使用
    collections.synchronizedXxx()
    方法进行同步
  • 2004年添加的Java 5.0并发集合支持无锁、线程安全的集合

简而言之,我建议您使用的所有集合都没有同步。

集合界面中的ArrayList、LinkedList、HashSet、LinkedHashset和TreeSet以及HashMap、LinkedHashMap和Treemap都是非同步的


采集界面中的向量已同步

同步会降低性能。当然,Java集合是不同步的。但是Java提供了一个同步包装器来同步Java集合

例如:
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Iterator;
导入java.util.List;
公共类SynchronizedListExample{
公共静态void main(字符串[]args){
List syncList=Collections.synchronizedList(新的ArrayList());
syncList.add(“一”);//此处无需同步
添加(“两个”);
添加(“三”);
String st=syncList.get(0);//这里没有问题=>不需要同步
//在对同步列表进行迭代时,我们需要同步对同步列表的访问
//因为如果您不在这里同步,synchList可能会在迭代过程中更改
已同步(同步列表){
迭代器迭代器=syncList.Iterator();
while(iterator.hasNext()){
System.out.println(“项:“+iterator.next());
}
}
}
}

前面的示例完全错误

首先,您没有从不同的线程访问刚刚同步的列表,您无法证明同步正在正确执行,您无法证明添加进程是原子的。其次,列表上的synchronized子句本身是一种不好的做法,您不知道优化器是否会使用列表中的某个项来执行同步,从而导致意外行为。此外,同步的是对列表中元素的读/写访问,而不是列表本身。取出Collections.synchronized并查看输出。尝试很多次。 请举以下例子:

class ProcessSomething {
    private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
    private void calculate() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    private void calculate2() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    public void process() {
        Long start = System.currentTimeMillis();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                calculate();
            }
        });
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                calculate2();
            }
        });
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
        }
        Long end = System.currentTimeMillis();
        System.out.println("Duration: " + (end - start));
        System.out.println("List size: " + integerList.size());
    }
}
public class App {
    public static void main(String[] args) {
        new ProcessSomething().process();
    }
}
类处理某些东西{
private List integerList=Collections.synchronizedList(new ArrayList());
私有无效计算(){
对于(int i=0;i<10000;i++){
试一试{
睡眠(1);
}捕获(中断异常例外){
Logger.getLogger(App.class.getName()).log(Level.SEVERE,null,ex);
}
add(new Random().nextInt(100));
}
}
私有void calculate2(){
对于(int i=0;i<10000;i++){
试一试{
睡眠(1);
}捕获(中断异常例外){
Logger.getLogger(App.class.getName()).log(Level.SEVERE,null,ex);
}
add(new Random().nextInt(100));
}
}
公共程序(){
长启动=System.currentTimeMillis();
线程t1=新线程(新的可运行线程(){
公开募捐{
计算();
}
});
t1.start();
线程t2=新线程(新可运行(){
公开募捐{
计算2();
}
});
t2.start();
试一试{
t1.join();
t2.连接();
}捕获(中断异常例外){
Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE,null,ex);
}
Long end=System.currentTimeMillis();
System.out.println(“持续时间:”+(结束-开始));
System.out.println(“列表大小:+integerList.size());
}
}
公共类应用程序{
公共静态void main(字符串[]args){
新的ProcessSomething().process();
}
}
java.util包中的所有集合类(Vector和Hashtable除外)都不是线程安全的仅有的两个传统集合是线程安全的:Vector和Hashtable。为什么? 原因如下:同步可能非常昂贵! 您知道,Vector和Hashtable是Java历史早期存在的两个集合,它们从一开始就是为线程安全而设计的(如果您有机会查看它们的源代码,您将看到它们的方法都是同步的!)。但是,它们很快就会暴露出多线程程序中的低性能。您可能知道,同步需要锁,而锁总是需要时间来监视,这会降低性能。 Tha
class ProcessSomething {
    private List<Integer> integerList = Collections.synchronizedList(new ArrayList<>());
    private void calculate() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    private void calculate2() {
        for (int i = 0; i < 10000; i++) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
            }
            integerList.add(new Random().nextInt(100));
        }
    }
    public void process() {
        Long start = System.currentTimeMillis();
        Thread t1 = new Thread(new Runnable() {
            public void run() {
                calculate();
            }
        });
        t1.start();
        Thread t2 = new Thread(new Runnable() {
            public void run() {
                calculate2();
            }
        });
        t2.start();
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException ex) {
            Logger.getLogger(ProcessSomething.class.getName()).log(Level.SEVERE, null, ex);
        }
        Long end = System.currentTimeMillis();
        System.out.println("Duration: " + (end - start));
        System.out.println("List size: " + integerList.size());
    }
}
public class App {
    public static void main(String[] args) {
        new ProcessSomething().process();
    }
}
List<String> syncList = Collections.synchronizedList(new ArrayList<String>());