目录
单例设计模式
单例设计模式:
保证类在内存中只有一个对象。
如何保证类在内存中只有一个对象呢?
(1)控制类的创建,不让其他类来创建本类的对象。private
(2)在本类中定义一个本类的对象。Singleton s;
(3)提供公共的访问方式。 public static Singleton getInstance(){return s}
单例写法两种:
第一种格式 饿汉式 推荐开发用这种方式
演示:
/* * 饿汉式 更好,在开发的时候用 * 上来就想吃(上来就想new 对象) */ class Singleton{ //1.私有构造方法 ,其他类不能访问该构造方法了,即不能创建此类对象 private Singleton() {} //2.创建本类对象 private static Singleton s = new Singleton(); //s是成员变量,必须用对象去调用他,但现在没有对象,我们就只能用类名.调用 所以加上静态 //3.对外提供公共的访问方法 public static Singleton getInstance() { //getInstance 获取实例(对象) return s; } }
第二种格式 懒汉式 面试写这种方式
演示:
/* * 懒汉式 * 先声明引用,然后再做一个判断,啥时候需要再创建对象 * 为什么不好: * 如果是多线程访问,第一条线程进行判断s == null,条件满足进入if内部,刚准备执行内部代码块。 * 这时不小心线程的执行权被别的线程抢去了,结果线程一在s = new Singleton();语句前等待 ,这时线程二进入if内部(线程二 s == null) * 线程一突然抢回执行权,线程二在s = new Singleton();语句前等待,线程一创建一个对象,return s给返回了。线程二接着也抢到执行权,创建一个对象。 * 这样,一共创建两次对象,就不是单例设计模式了。因此,懒汉式在多线程访问的时候,他会有安全隐患————他有可能会创建多个对象出来。 * 所以,懒汉式只在面试的时候用。 面试时,他让你写一个单例的延迟加载模式,其实问的就是懒汉式。 */ class Singleton{ //1.私有构造方法 ,其他类不能访问该构造方法了,即不能创建此类对象 private Singleton() {} //2.声明一个引用 private static Singleton s ; //3.对外提供公共的访问方法 public static Singleton getInstance() { if(s == null) { //s == null 没有创建对象 s = new Singleton(); } return s; } }
第三种格式 没名字
演示:
class Singleton{ //1.私有构造方法 ,其他类不能访问该构造方法了,即不能创建此类对象 private Singleton() {} //2.声明一个引用 public static final Singleton s = new Singleton(); //加final,s不可改变 }
饿汉式和懒汉式的区别
1.饿汉式是空间换时间 上来就去创建一个对象,把空间给浪费了。但是节省了时间,因为你想要,我只接就返回给你。现在时间更重要
懒汉式是时间换空间 上来做个声明,不去创建,什么时候用什么时候给你创建。调用方法的时候做判断s == null,判断就浪费了我们的时间,每一次都要做判断,每一次都浪费时间,比较亏
2.在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象。
Runtime类(懒汉式单例设计模式的应用场景)
Runtime类是一个单例类,概述:
public class Runtime extends Object 每个Java应用程序都有一个Runtime类实例,使应用程序能够与其运行的环境相连接。可以通过getRuntime方法获取当前运行时。
应用程序不能创建自己的Runtime类实例。
api中没有构造方法(一个类里没有构造方法,说明构造方法被私有了),但并不是所有方法都为静态。
Runtime类的成员方法:
public static Runtime getRuntime() 返回与当前Java应用程序相关的运行时对象。(说明这个类其实是私有构造。在本类创建对象,对外提供这么一个公共的访问方式。)
源代码:
private static Runtime currentRuntime = new Runtime(); //私有了一个本类对象 自己创建了一个本类对象 currentRuntime当前的一个运行时对象 public static Runtime getRuntime() { return currentRuntime; //返回这个currentRuntime } private Runtime() {} //私有构造方法
private Runtime() {} //私有构造方法
public Process exec(String command) 在单独的进程中执行指定的字符串命令。
演示:
public class Demo2_Runtime {
public static void main(String[] args) throws IOException {
Runtime r = Runtime.getRuntime(); //获取运行时对象
// r.exec("shutdown -s -t 300"); //设置系统在5分钟后关机 第一次把系统给修改了
r.exec("shutdown -a"); //取消注销计划(不会关机了) 第二次修改你修改后的结果,我们操作的是同一个对象 这就需要用到单例设计模式
}
}
Timer类
Timer类:计时器,概述:
public class Timer extends Object 一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
与每个Timer对象相对应的是单个后台线程,用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占“计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能”堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。
对Timer对象最后的引用完成后,并且所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是这可能要很长时间后才发生。默认情况下,任务执行线程并不作为守护线程来运行,所以他能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,那么调用者应该调用计时器的cancel方法。
如果意外终止了计时器的任务执行线程,例如调用了它的stop方法。那么所有以后对该计时器安排的尝试都将导致IllegalStateException,就好像调用了计时器的cancel方法一样。
此类是线程安全的:多个线程可以共享单个Timer对象而无需进行外部同步。
此类不提供实时保证:它使用Object.wait(long)方法来安排任务。
实现注意事项:此类可扩展到大量同时安排的任务(存在数千个都没有问题)。在内部,它使用二进制堆来表示其任务队列,所以安排任务的开销是O(log n),其中n是同时安排的任务数。
实现注意事项:所有构造方法都启动计时器线程。
Timer类的成员方法:
public void schedule(TimerTask task, Date time) 安排在指定的时间执行指定的任务。
public void schedule(TimerTask task, Date firstTime, long period) 安排指定的任务在指定的时间开始进行重复的固定延迟执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。
在固定延迟执行中,根据前一次执行的实际执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则后续执行也将被延迟。在长期运行中,执行的频率一般要稍慢于指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。
固定延迟执行适用于那些需要“平稳”运行的重复执行活动。换句话说,它适用于在短期运行中保持频率准确要比在长期运行中更为重要的活动。这包括大多数动画任务,如以固定时间间隔闪烁的光标。这还包括为响应人类活动所执行的固定活动,如在按住键时自动重复输入字符。
TimerTask类的概述:
public abstract class TimerTask extends Object implements Runnable 由Timer安排为一次执行或重复执行的任务。
TimerTask类的成员方法:
public abstract void run() 此计时器任务要执行的操作。父类实现了Runnable接口,所以run()来自于Runnable接口。该方法抽象,所以任务是交给子类去完成的。
Date类(util包下的)的成员方法:
public Date(int year, int month, int date, int hrs, int min, int sec) 已过时。 从 JDK 1.1 开始,由 Calendar.set(year + 1900, month, date, hrs, min, sec) 或 GregorianCalendar(year + 1900, month, date, hrs, min, sec) 取代。
分配 Date 对象,并初始化此对象,以表示本地时区中由 year、month、date、hrs、min 和 sec 参数指定的秒的开始瞬间。