为什么JAVA很多类都放弃了安全而要速度呢

比如hashmap和hashtable,arrylist和vector这种的,我学的时候都说是xxx不用了,区别是一个安全一个不安全,当然hashtable那个还有个null的区别,为啥要用不安全的呢

阅读 5.3k
7 个回答

什么叫放弃安全而要速度
这认识错的太远了,需要线程安全的情况下当然是必须要使用线程安全的类型了,不需要自然是可以不用使用了。

如下代码

public void m() {
    int i = 0;
    String s = "string" + i;
    System.out.println(s);
}

JDK会将字节码编译成如下

  public void m();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=3, args_size=1
         0: iconst_0
         1: istore_1
         2: new           #2                  // class java/lang/StringBuilder
         5: dup
         6: invokespecial #3                  // Method java/lang/StringBuilder."<init>":()V
         9: ldc           #4                  // String string
        11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        14: iload_1
        15: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
        18: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
        21: astore_2
        22: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
        25: aload_2
        26: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        29: return

可以很清楚的看到字节码中将字符串连接编译成StringBuilder的方式,我们知道JDK还提供了一个StringBuffer线程安全的字符串操作类。那JDK编译时为什么不选择StringBuffer来做呢,答案很显然是不需要,因为这是在一个方法的内部,一个局部变量是不可能会遇到线程安全问题的。

HashMapHashTable也是同理,如果你是局部变量那只需要选择HashMap就可以了。如果是全局变量且会有多个线程同时操作该变量的情况当然是不能选择HashMap,而是要选择HashTable这种线程安全的类型,但是现在HashTable被选择的也会很少是因为有了更好的选择如ConcurrentHashMap来代替。

你开车需要系安全带,骑摩托车需要带头盔,但是并不代表你在家睡觉也要系安全带带头盔(当然你不嫌麻烦也可以这么干)。

在单线程环境下(~在家睡觉~),你可以使用线程安全或者非现场安全的类,但是非现场安全的类通常性能更高,且在单线程情况下也不存在安全问题。

在多线程的情况下(~开车骑摩托车~),你必须牺牲性能,用线程安全的类。

因为使用场景有并发和非并发的区别。如果非得需要解决线程安全问题,比如集合类,它又提供了一个集合的工具类实现同步。个人理解,先追求速度,这能给用户带来体验,安全性如果需要就还可以扩展。

鱼与熊掌不可兼得,线程安全通常都是要加锁和解锁的,不但会对设计上造成复杂性(比如要想办法避免死锁问题),而且会对性能造成显著的影响。

而绝大多数场景下都是单线程同步模型,压根不用考虑线程安全问题。

如果我理解你的问题正确: 为什么不是所有的Collections都是线程安全的?原因有:

  • 实现线程安全是非常困难,如果不是不可能的
  • 牺牲性能代价可能很大
  • 大多数应用场景下线程安全是不必要的。

所以说,你的问题看起来有点像:“有总比没有好,用不用是我的事”,答案是:“有不是总比没有好,有是需要付出代价,而这代价通常你不需要付出或尽量避免的”。因为Map/List/...应用的场景通常不需要线程安全的,所以在绝大多数的情况下HashTable/Vector/...被HashMap/ArrayList/...代替了

不线程安全才是默认状态。如果不特意做些事情,基本上没有东西是线程安全。所以谈不上 "放弃"。

不线程安全不等于没用,有一些情况是不需要线程安全的,少做这些事的代码可能更快。

========================我的答案==============================
项目大多数情况都是单线程同步的,不需要考虑多线程问题(也就是线程安不安全)。所以速度快是默认选项,只有到了要用多线程的时候才会去考虑安不安全。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题