先看饿汉模式:
package com.zyzs.Singleton;
public class Singleton {
private static Singleton singleton =new Singleton();
//获取实例对象
public static Singleton getInstance(){
return singleton;
}
public static void main(String[] args) {
//此方法不存在线程安全问题--不存原子操作
System.out.println(Singleton.getInstance());
System.out.println(Singleton.getInstance());
}
}
优缺点:此模式不存在线程安全性问题,因为对象再初始化时候已经加入内存,线程只对对象进行读取操作,不存在原子操作,但是对于加载大的对象或者比较耗费性能的对象而言,饿汉模式显然会占用更多资源。
懒汉模式:
第一种情况:
package com.zyzs.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class Singleton2 {
private static Singleton2 singleton;
//获取实例对象
public static Singleton2 getInstance(){
if(singleton==null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
singleton=new Singleton2();
}
return singleton;
}
public static void main(String[] args) {
ExecutorService executorService =Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = (Future<String>) executorService.submit(new TaskWithResult());
// 将任务执行结果存储到List中
resultList.add(future);
}
executorService.shutdown();
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
class TaskWithResult implements Callable<String> {
@Override
public String call() throws Exception {
return Singleton2.getInstance().toString();
}
}
1.附带测试案例,此对象会存在线程安全问题,不建议在多线程环境下使用
第二种情况:
package com.zyzs.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class Singleton3 {
private static Singleton3 singleton;
//获取实例对象
public static synchronized Singleton3 getInstance(){
//此处存在自旋操作--比较好性能--和单例没有区别
if(singleton==null){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
singleton=new Singleton3();
}
return singleton;
}
public static void main(String[] args) {
ExecutorService executorService =Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = (Future<String>) executorService.submit(new TaskWithResult3());
// 将任务执行结果存储到List中
resultList.add(future);
}
executorService.shutdown();
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
class TaskWithResult3 implements Callable<String> {
@Override
public String call() throws Exception {
return Singleton3.getInstance().toString();
}
}
此方法虽然能保证线程安全,但是对方法的加锁会导致线程的自旋操作,会占用较多资源,耗费性能,建议使用第三中
第三种:
package com.zyzs.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
public class Singleton4 {
private static Singleton4 singleton;
//获取实例对象
public static Singleton4 getInstance(){
//此处存在自旋操作--比较好性能--和单例没有区别
if(singleton==null){
synchronized(Singleton4.class){
if(singleton==null){
singleton=new Singleton4();
}
}
}
return singleton;
}
public static void main(String[] args) {
ExecutorService executorService =Executors.newCachedThreadPool();
List<Future<String>> resultList = new ArrayList<Future<String>>();
// 创建10个任务并执行
for (int i = 0; i < 10; i++) {
// 使用ExecutorService执行Callable类型的任务,并将结果保存在future变量中
Future<String> future = (Future<String>) executorService.submit(new TaskWithResult4());
// 将任务执行结果存储到List中
resultList.add(future);
}
executorService.shutdown();
// 遍历任务的结果
for (Future<String> fs : resultList) {
try {
System.out.println(fs.get()); // 打印各个线程(任务)执行的结果
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
executorService.shutdownNow();
e.printStackTrace();
return;
}
}
}
}
class TaskWithResult4 implements Callable<String> {
@Override
public String call() throws Exception {
return Singleton4.getInstance().toString();
}
}
此种方式在方法块进行加锁,缩小加锁范围,使用双重验证进行实例初始化,建议使用此方法
了解更多加微信 aa544731152,拉你入群