适用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
1.需要频繁实例化然后销毁的对象。
2.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3.有状态的工具类对象。
4.频繁访问数据库或文件的对象。
以下都是单例模式的经典使用场景:
1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
2.控制资源的情况下,方便资源之间的互相通信。如线程池等。
demo代码:
1
/**
* 使用单例模式获取日志文件的实例对象,避免了一个文件多次被打开造成的异常
* 文件只能被一个进程打开。改进:使用工厂方法来创建文件实例对象,周期线程池来进行资源的释放
*/
public class FileOperate { 2 private static String filePath="D:/test/file.log"; 3 4 //volatile 保证赋值执行的有序性,不会出现fileOutputStream已有分配空间但还没实例对象初始化的情况 5 private static volatile FileOutputStream fileOutputStream=null; 6 public static synchronized FileOutputStream getInstance(){//synchronized保证即便执行线程中断也持有锁 7 if(fileOutputStream==null){ 8 File file=new File(filePath); 9 try{ 10 if(!file.exists()){ 11 file.createNewFile(); 12 } 13 fileOutputStream=new FileOutputStream(file,true); 14 }catch (Exception e){ 15 e.printStackTrace(); 16 } 17 } 18 return fileOutputStream; 19 } 20 21 public static synchronized void fileWrite(String content){ 22 System.out.println("执行:"+Thread.currentThread().getName()); 23 FileOutputStream fileOutputStream=getInstance(); 24 try{ 25 byte[] bytes=content.getBytes("utf-8"); 26 fileOutputStream.write(bytes); 27 fileOutputStream.flush(); 28 }catch (IOException e){ 29 e.printStackTrace(); 30 } 31 finally { 32 System.out.println(Thread.currentThread().getName()+"执行完毕"); 33 } 34 } 35 36 public static void main(String[] args) { 37 ExecutorService executorService= Executors.newFixedThreadPool(2); 38 for (int i=0;i<5;i++){ 39 Thread thread=new Thread(){ 40 public void run(){ 41 fileWrite(Thread.currentThread().getName()+":"+UUID.randomUUID().toString()+" "); 42 } 43 }; 44 executorService.execute(thread); 45 } 46 executorService.shutdown(); 47 } 48 49 }
日志代码优化:
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 使用单例模式获取日志文件的实例对象,避免了一个文件多次被打开造成的异常 * */ public class FileOperateOptimize implements Runnable { private String filePath=""; private FileFactory fileFactory=null; public FileOperateOptimize(String filePath){ this.fileFactory=fileFactory; this.filePath=filePath; } //volatile 保证赋值执行的有序性,不会出现fileOutputStream已有分配空间但还没实例对象初始化的情况 private volatile FileOutputStream fileOutputStream=null; public synchronized FileOutputStream getInstance(){//synchronized保证即便执行线程中断也持有锁 if(fileOutputStream==null){ File file=new File(filePath); try{ if(!file.exists()){ file.createNewFile(); } fileOutputStream=new FileOutputStream(file,true); }catch (Exception e){ e.printStackTrace(); } } return fileOutputStream; } public synchronized void fileWrite(String content){ System.out.println("执行:"+Thread.currentThread().getName()); FileOutputStream fileOutputStream=getInstance(); try{ byte[] bytes=content.getBytes("utf-8"); fileOutputStream.write(bytes); fileOutputStream.flush(); }catch (IOException e){ e.printStackTrace(); } finally { System.out.println(Thread.currentThread().getName()+"执行完毕"); } } public void run(){ try { fileOutputStream.close(); FileFactory.remove(filePath); }catch (Exception e){ e.printStackTrace(); } } }
import java.util.Map; import java.util.concurrent.*; public class FileFactory{ private static Map<String,FileOperateOptimize> hashMap=new ConcurrentHashMap();//保存文件输入流 private static ScheduledExecutorService executorService=Executors.newScheduledThreadPool(5); public static FileOperateOptimize newFileOperateOptimize(String filePath) { if(hashMap.get(filePath)!=null){ return hashMap.get(filePath); }else { FileOperateOptimize fileOperateOptimize= new FileOperateOptimize(filePath); hashMap.put(filePath,fileOperateOptimize); executorService.schedule(fileOperateOptimize,3, TimeUnit.MINUTES);//超过一定时间对资源释放 return fileOperateOptimize; } } public static void remove(String filePath){//访问者模式 hashMap.remove(filePath); } }
import java.util.Date; import java.util.UUID; public class Test { public static void main(String[] args) { String path1="D:/test/file1.log"; String path2="D:/test/file2.log"; for(int i=0;i<100;i++){ FileFactory.newFileOperateOptimize(path1).fileWrite(i+":"+new Date().toString()+":"+ UUID.randomUUID().toString()+" "); FileFactory.newFileOperateOptimize(path2).fileWrite(i+":"+new Date().toString()+":"+ UUID.randomUUID().toString()+" "); } } }