单例模式

适用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
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()+"\n"); 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()+"\n");
            FileFactory.newFileOperateOptimize(path2).fileWrite(i+":"+new Date().toString()+":"+ UUID.randomUUID().toString()+"\n");
        }
    }
}

 

posted @ 2020-05-27 16:29  骑猪飞天  阅读(130)  评论(0编辑  收藏  举报