java线程死亡

也有标题; 我的宠物讨厌Java编码。

有许多Java模因让我很烦,部分是因为它们总是一个坏主意,但主要是因为人们在找到更好的替代方案后的几年里仍在不断地选择它们。

使用StringBuffer代替StringBuilder

从2004年开始,用于StringBuffer的Javadoc

从JDK 5版本开始,该类已经添加了一个等效类,该类旨在供单线程StringBuilder使用。 通常应优先使用StringBuilder类,因为它支持所有相同的操作,但它更快,因为它不执行同步,因此它比所有此类都优先使用。

StringBuilder不仅是一个更好的选择,而且本来可以使用同步StringBuffer的情况如此罕见,这与以往是个好主意。

说你有代码

// run in two threads
sb.append(key).append("=").append(value).append(", ");

每个附录都是线程安全的,但是可以随时释放该锁,这意味着您可以

key1=value1, key2=value2, 
key1=key2value1=, value2, 
key1key2==value1value2, ,

更糟糕的是,为了提高效率,JIT和JVM将试图在两次调用之间保持锁定。 这意味着您可以拥有可以通过所有测试并可以在生产环境中使用多年的代码,但是很少中断,这可能是由于升级JVM所致。

使用DataInputStream读取文本

另一个常见的模因是,在阅读以下模板中的文本时使用DataInputStream(三行,两个阅读器位于同一行),我怀疑有一个原始代码被复制了。

FileInputStream fstream = new FileInputStream("filename.txt");  
DataInputStream in = new DataInputStream(fstream);  
BufferedReader br = new BufferedReader(new InputStreamReader(in));

这很不好,原因有三个

  • 由于BufferedReader的缓冲性质,您可能会倾向于使用in来读取无法使用的二进制文件。 (我已经看到了这个尝试)
  • 同样,您可能会相信DataInputStream在不这样做的情况下会在此处做有用的事情
  • 有一种更短的方法是正确的。
BufferedReader br = new BufferedReader(new FileReader("filename.txt")); 
// or with Java 7.
try (BufferedReader br = new BufferedReader(new FileReader("filename.txt")) {
    // use br
}

使用双重检查锁定创建单例

首次使用双重检查锁定时,这是一个坏主意,因为JVM不安全地支持此操作。

// Singleton with double-checked locking:
public class Singleton {
    private volatile static Singleton instance;

    private Singleton() { }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

问题在于,直到Java 5.0为止,这种方法通常都有效,但在内存模型中无法保证。 有一个更简单的选项是安全的,不需要显式锁定。

// suggested by Bill Pugh
public class Singleton {
    // Private constructor prevents instantiation from other classes
    private Singleton() { }

    /**
     * SingletonHolder is loaded on the first execution of Singleton.getInstance()
     * or the first access to SingletonHolder.INSTANCE, not before.
     */
    private static class SingletonHolder {
        public static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

这仍然很冗长,但是可以正常工作,并且不需要显式锁定,因此可以更快。

在Java 5.0中,当他们修复内存模型以安全地处理双重锁定时,他们还引入了枚举,从而为您提供了更为简单的解决方案。

约书亚·布洛赫(Joshua Bloch)在他的第二本书《有效的Java》中声称“单元素枚举类型是实现单例的最佳方法”

使用枚举,代码看起来像这样。

public enum Singleton {
    INSTANCE;
}

这是延迟加载的,线程安全的,没有显式锁且更简单。

参考: Java模因拒绝在Vanilla Java博客上死于我们的JCG合作伙伴 Peter Lawrey。

翻译自: https://www.javacodegeeks.com/2012/08/java-memes-which-refuse-to-die.html

java线程死亡