[Notes9] template, singleton


1. Template: there are abstract methods in the class must be abstract

Decorator (IO stream), iterator (collection)

package com.atguigu.test02.abstract_;
// 编写一个类,包含一个方法,可以统计  你执行任意代码的运行时间
public class TestTemplate {
    
    
	public static void main(String[] args) {
    
    
		MyCalTime my = new MyCalTime();
		long time = my.getTime();				
		System.out.println("耗时:" + time + "毫秒");
	}
}

abstract class CalTime{
    
     //模板类
	//可以计算任意一段代码的运行时间 //这里加final的目的是不希望子类重写,改写我的算法的结构
	public final long getTime(){
    
    		
		long start = System.currentTimeMillis(); //(1)获取开始时系统时间	 			
		doWork(); //(2)执行xxxx			
		long end = System.currentTimeMillis();	//(3)获取结束时系统时间							
		return end - start; //(4)计算时间差
	}	
	protected abstract void doWork(); //protected的目的,希望只是子类中进行访问和重写
}

class MyCalTime extends CalTime{
    
    
	@Override
	protected void doWork() {
    
     //重写抽象方法
		long sum = 0;
		for(int i=1; i<=100000; i++){
    
    
			sum += i;
		}
		System.out.println("sum = " + sum);
	}	
}

Insert picture description here

2. Singleton: multi-threaded

package com.atguigu.test17;
import org.junit.Test;
/*
 * 单例:某个类只能有唯一的一个实例对象。如何实现单例?
 * 1、饿/恶汉式: 不管我们使用者是否需要这个对象,它都上来先给你创建好这个唯一的对象。
 *     (1)枚举类型
 * 
 *     (2)形式二:class SingleClass
 *                ①构造器私有化
 *                ②用一个全局的静态的常量,来保存这个唯一的实例对象
 * 
 *     (3)形式三:class Single
 *                ①构造器私有化
 * 			      ②用一个私有的静态的常量,来保存这个唯一的实例对象
 * 			      ③提供一个静态方法,来返回这个常量对象
 * 
 * 
 * 2、懒汉式: 延迟创建对象。当使用者来或者这个对象,要用到对象时,我再创建。
 *     (1)形式一:见下面,考虑线程安全问题和性能问题
 *     (2)形式二:内部类形式
 */
public class Test17 {
    
    
	@Test
	public void test1(){
    
    
		SingleEnum s1 = SingleEnum.INSTANCE;
		SingleEnum s2 = SingleEnum.INSTANCE;
		System.out.println(s1 == s2); //true 
	}	
	
	@Test
	public void test2(){
    
    
    // SingleEnum.test();//此时我并没有需要用到这个INSTANCE对象,但是它也创建出来SingleEnum对象,单例恶汉式
	}	
	
	@Test
	public void test3(){
    
    
		SingleClass s1 = SingleClass.INSTANCE;
		SingleClass s2 = SingleClass.INSTANCE;
		System.out.println(s1==s2); //true,地址一样,只有一个对象。
	}
		
	@Test
	public void test4(){
    
    
		Single s1 = Single.getInstance();
		Single s2 = Single.getInstance();
		System.out.println(s1 == s2); //true
	}	

	@Test
	public void test5(){
    
    
		LazyClass s1 = LazyClass.getInstance(); //getInstance()里必有new
		LazyClass s2 = LazyClass.getInstance();
		System.out.println(s2 == s1);
	}
		
	LazyClass s1;
	LazyClass s2;	
	@Test
	public void test6(){
    
    
		//匿名的内部类,继承Thread类。=后面是子类,然后多态
		Thread t1 = new Thread(){
    
    
			public void run(){
    
    
				s1 = LazyClass.getInstance();
			}
		};		
		Thread t2 = new Thread(){
    
    
			public void run(){
    
    
				s2 = LazyClass.getInstance();
			}
		};		
		t1.start();
		t2.start();		
		try {
    
    
			//这里用join的目的是,为了两个子线程都执行完,再执行主线程的System.out.println(s1);
			t1.join();
			t2.join();
		} catch (InterruptedException e) {
    
    
			e.printStackTrace();
		}		
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(s1 == s2);
	}	
}

//111111111111111111111111111111111111111111111111111111111111111111111111111111111饿汉式
enum SingleEnum{
    
    
	INSTANCE; //单例,枚举只有一个   //对应test1()
//	public static void test(){ //用这个方法不用上面这个INSTANCE对象   //对应test2()
      	//..
//	}
}

//形式二   //对应test3() 
class SingleClass{
    
     //1.5之前老版的枚举 
	public static final SingleClass INSTANCE = new SingleClass();
	private SingleClass(){
    
    		
	}
}

//形式三  //对应test4() 
class Single{
    
      
	private static final Single INSTANCE = new Single();
	private Single(){
    
    		
	}
	public static Single getInstance(){
    
       
		return INSTANCE;
	}
}

//11111111111111111111111111111111111111111111111111111111111111111111111111111111懒汉式
//形式一
class LazyClass{
    
     //对应test6()
	private static LazyClass instance; //不加final,可以不用new出来  //加final必须new SingleClass()
	private LazyClass(){
    
    		
	}	
	public static LazyClass getInstance(){
    
     
		if(instance == null){
    
    //提高效率,已创建对象就没必要再进去,直接最后return instance; 未创建对象进入
			synchronized(LazyClass.class){
    
     //当前类的Class对象,静态方法不能出现this
				if(instance == null){
    
    //安全判断
					try {
    
    
						Thread.sleep(100);
					} catch (InterruptedException e) {
    
    
						e.printStackTrace();
					}
					instance = new LazyClass();
				}
			}
		}
		return instance;
	}	

//安全没问题,但是认为不是最优的,性能差。
//instance对象创建好了,第一次和第二次有竞争关系,后面没必要再等锁,对象已经new好了,直接拿就行  
/* public synchronized static LazyClass getInstance(){ 
		if(instance == null){
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			instance = new LazyClass();
		}
		return instance;
	}*/	
	
//有线程安全问题 如下图所示 
/*	public static LazyClass getInstance(){
//		return new LazyClass();//错误的,每次都new新的对象
		if(instance == null){ //下次有的时候就不进来了
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			instance = new LazyClass();
		}
		return instance;
	}*/
}
 
//形式二 
class Lazy{
    
    
	private Lazy(){
    
    		
	}	
	private static class Inner{
    
    
		public static final Lazy INSTANCE = new Lazy();//在内部类中,创建外部类的唯一对象
	}	
	public static Lazy getInstance(){
    
     
		return Inner.INSTANCE; //用到getInstance方法才会new Lazy(),也是懒汉式
	}
}

The following figure corresponds to test5(), and it prints false because it is new every time.
Insert picture description here
Add Thread.sleep(100) to the white line in the following figure.
Insert picture description here
Station B/Zhihu/WeChat Official Account: Code Farming Programming Record
Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43435675/article/details/111087912