//线程安全的
public class Singleton {
//单例模式,构造器要私有化。
private Singleton() {}
//私有的静态的常量--私有静态引用指向自己实例。
//【因为是static修饰的属性,所以是在类加载的时候就被创建,
//后期不会再改变,所以线程是安全的!】
private static final Singleton single = new Singleton();
//以自己实例为返回值的公有静态方法。
public static Singleton getInstance() {
return single;
}
}
懒汉式单例:
java复制代码
//有线程安全的问题,不推荐使用
//就算是使用了[加锁+双重判断]的解救办法,性能还是被损耗了。
public class SingletonTest {
public static SingletonTest singleton = null;
public static SingletonTest getInstance(){
if(singleton == null){
singleton = new SingletonTest();
}
return singleton;
}
//单例模式,构造器要私有化
private SingletonTest {
}
}
DCL(Double Check双重判断 + Lock加锁)懒汉式单例但线程安全,推荐使用:
java复制代码
//线程安全的
public class Singleton {
private volatile static Singleton singleton;
public static Singleton getSingleton(){
//双重判断之一
if(singleton==null){
//加锁
synchronized (Singleton.class) {
//双重判断之二
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
//构造函数私有化
private Singleton(){
}
}
静态内部类(懒汉式单例但线程安全):
java复制代码
//线程安全的
//外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE,故而不占内存。
//第一次调用getInstance()方法会导致虚拟机加载SingleTonHoler类且初始化INSTANCE。
//在创建时是否有并发问题? => 没有没有,类加载时jvm会保证线程安全性!
public class Singleton {
//静态内部类
private static class SingleTonHoler{
private static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingleTonHoler.INSTANCE;
}
//单例模式,构造器要私有化
private Singleton {
}
}
枚举类(饿汉式):
java复制代码
//枚举单例属于懒汉式还是饿汉式:饿汉式,内部枚举类相当于静态成员变量,
//类加载时就会创建,因此也是线程安全的。
public class SingletonObject7 {
private SingletonObject7(){
}
/**
* 枚举类型是线程安全的,并且只会装载一次
*/
private enum Singleton{
INSTANCE;
private final SingletonObject7 instance;
Singleton(){
instance = new SingletonObject7();
}
private SingletonObject7 getInstance(){
return instance;
}
}
public static SingletonObject7 getInstance(){
//内部枚举类相当于静态成员变量
return Singleton.INSTANCE.getInstance();
}
}
public abstract class InputStream implements Closeable {
//抽象方法,要求子类必须重写
public abstract int read() throws IOException;
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if (off < 0 || len < 0 || len > b.length - off) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
int c = read(); //调用了无参的read方法,该方法是每次读取一个字节数据
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
}
在InputStream类中定义了多个 read() 方法,从上面代码可以看到,++无参的 read() 方法是抽象方法,要求子类必须实现++。而 read(byte b[]) 方法调用了 read(byte b[], int off, int len) 方法,所以在此处重点看的方法是带三个参数的方法。 在该方法中可以看到调用了无参的抽象的 read() 方法。