• 单例设计模式


    单例设计模式

    比较常见的有spring提供的ioc,控制翻转,只需要加一个componet注解,默认注解修饰的对象就是单例的
    如果自己要实现一个单例,应该是如何一个思路呢

    借鉴xxl-job里面客户端的代码

    功能:一个线程后台起,每隔1天去扫描一下日志文件,只保留最近的30个日志文件的功能

    代码样例

    public class JobLogFileCleanThread {
        private static Logger logger = LoggerFactory.getLogger(JobLogFileCleanThread.class);
    
        private static JobLogFileCleanThread instance = new JobLogFileCleanThread();
        public static JobLogFileCleanThread getInstance(){
            return instance;
        }
    
        private Thread localThread;
        private volatile boolean toStop = false;
        public void start(final long logRetentionDays){
    
            // limit min value
            if (logRetentionDays < 3 ) {
                return;
            }
    
            localThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while (!toStop) {
                        try {
                            // clean log dir, over logRetentionDays
                            File[] childDirs = new File(XxlJobFileAppender.getLogPath()).listFiles();
                            if (childDirs!=null && childDirs.length>0) {
    
                                // today
                                Calendar todayCal = Calendar.getInstance();
                                todayCal.set(Calendar.HOUR_OF_DAY,0);
                                todayCal.set(Calendar.MINUTE,0);
                                todayCal.set(Calendar.SECOND,0);
                                todayCal.set(Calendar.MILLISECOND,0);
    
                                Date todayDate = todayCal.getTime();
    
                                for (File childFile: childDirs) {
    
                                    // valid
                                    if (!childFile.isDirectory()) {
                                        continue;
                                    }
                                    if (childFile.getName().indexOf("-") == -1) {
                                        continue;
                                    }
    
                                    // file create date
                                    Date logFileCreateDate = null;
                                    try {
                                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                                        logFileCreateDate = simpleDateFormat.parse(childFile.getName());
                                    } catch (ParseException e) {
                                        logger.error(e.getMessage(), e);
                                    }
                                    if (logFileCreateDate == null) {
                                        continue;
                                    }
    
                                    if ((todayDate.getTime()-logFileCreateDate.getTime()) >= logRetentionDays * (24 * 60 * 60 * 1000) ) {
                                        FileUtil.deleteRecursively(childFile);
                                    }
    
                                }
                            }
    
                        } catch (Exception e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
    
                        }
    
                        try {
                            TimeUnit.DAYS.sleep(1);
                        } catch (InterruptedException e) {
                            if (!toStop) {
                                logger.error(e.getMessage(), e);
                            }
                        }
                    }
                    logger.info(">>>>>>>>>>> xxl-job, executor JobLogFileCleanThread thread destory.");
    
                }
            });
            localThread.setDaemon(true);
            localThread.setName("xxl-job, executor JobLogFileCleanThread");
            localThread.start();
        }
    
        public void toStop() {
            toStop = true;
    
            if (localThread == null) {
                return;
            }
    
            // interrupt and wait
            localThread.interrupt();
            try {
                localThread.join();
            } catch (InterruptedException e) {
                logger.error(e.getMessage(), e);
            }
        }
    
    }
    

    代码分析

    1. JobLogFileCleanThread 类就是一个单例模式,内部有一个静态变量instance,默认值是new JobLogFileCleanThread()自己本身
    2. 静态方法getInstance()取到的变量就是静态变量instance
    3. 为什么这个JobLogFileCleanThread的线程类自己本身没有继承Thread父类呢,而是里面又内嵌了一个Thread类型的localThread变量?
    4. JobLogFileCleanThread 自己有一个start方法,且是可以传递参数的,默认线程类Thread的start是不可以接受参数的,所以JobLogFileCleanThread类自己本身没有继承Thread类
    5. 可以看出start(long logRetentionDays)方法,内部起了一个new Thread的匿名内部类,并赋值给了变量localThread,匿名内部类里面写自己的业务逻辑,并且是个死循环,依赖一个flag标记,这个flag标记由voliate修饰,杜绝线程之间可见性问题也可以做到执行方法stop的时候,可以优雅关闭死循环的线程。
  • 相关阅读:
    利用python进行数据分析之数据聚合和分组运算
    利用python进行数据分析之绘图和可视化
    利用python进行数据分析之数据规整化
    利用python进行数据分析之pandas库的应用(二)
    利用python进行数据分析之pandas库的应用(一)
    利用python进行数据分析之数据加载存储与文件格式
    git 本地无版本仓库推送到远程新仓库命令
    Docker 部署Dotnet Core MVC项目
    css 单行图片文字水平垂直居中汇总
    IL命令初学者要知道的事
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/16084342.html
Copyright © 2020-2023  润新知