一、设计模式 (Design Patterns)分类
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
二、单例模式
特征:一个类只有一个实例对象。(举例:你,可以扮演儿子,丈夫,爸爸,员工,但是世界上只有一个你,这就是单例。)
三、简单案例
单例模式主要存在两种: 饿汉式 ,懒汉式
饿汉式代码 案例:
public final class Singleton {
private static final Singleton instance = new Singleton ();
private Singleton(){
//do something
}
public static Singleton getInstance(){
return instance;
}
}
懒汉式代码 案例(两种写法):
第一种:线程安全
public final class Singleton {
private volatile static Singleton intance=null;
private static Object INSTANCE_LOCKER = new Object();;
private Singleton(){
//do something
}
public static Singleton getSingleton(){
if(null==intance){
synchronized(INSTANCE_LOCKER){
if(null==intance){
intance = new Singleton();
}
}
}
return intance;
}
}
第二种:(静态内部类)
利用了classloder的机制来保证初始化instance时只有一个线程。显示调用getInstance方法时,才会显示装载SingletonHolder类,从而实例化instance。
public final class Singleton {
private static class SingletonHolder{
private static final Singleton INSTANCE= new Singleton ();
private SingletonHolder(){
}
}
private Singleton(){
//do something
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
注意:final
当final修饰一个类时,表明这个类不能被继承。
当final修饰一个方法时,第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。
当final修饰一个变量时,对其初始化之后便不能再让其指向另一个对象。(但是初始化对象的内部引用可以)。
四、案例场景
作用:资源共享,控制资源。
资源共享:读取配置文件,缓存单例工厂,多个线程共同计数。
控制资源:线程池的管理。
案例一:
读取配置文件:
/**
* 单例实例1
* 懒加载,懒汉式
* 案例:加载配置文件中的配置对象
*
*
*/
public class ConfigHelper {
//1.日志属性
//2.RemoteTransportServer核心属性对象
//List和Map相关容器,解析的配置对象
private static class LazyHolder
{
private static final ConfigHelper INSTANCE = new ConfigHelper();
private LazyHolder()
{
}
}
private ConfigHelper(){
//3.加载配置文件,解析配置文件为一个对象
//do something ,解析xml文件
init();
}
private void init(){
//4.实例化配置文件的中的对象,并做一些初始化工作
//do something ,根据xml配置,对类做一些初始化工作
}
//5.返回单例实例
public static final ConfigHelper getInstance()
{
return LazyHolder.INSTANCE;
}
//6.更新配置文件的内容
public void updateConfig(String server){
//1.Clear掉Map.clear(),Object=null;
//2.重新像构造方法中一样读取配置文件。
//do something ,重新解析xml文件
//3.初始化init()
init();
}
}
统一解析xml的工具框架
public class XMLHelper {
static
{
isInit = Boolean.FALSE;
isCacheInit = Boolean.FALSE;
}
private static Boolean isInit;
private static Boolean isCacheInit;
private static XMLHelper instance = null;
private static Defaults defaults = null;
private static Caches caches = null;
private XMLHelper()
{
}
public static XMLHelper getInstance()throws Exception
{
if(isInit.equals(Boolean.FALSE))
{
synchronized(isInit)
{
if(isInit.equals(Boolean.FALSE))
{
//主要的配置文件
defaults = createDefaults();
isInit = Boolean.TRUE;
}
}
instance = new XMLHelper();
}
return instance;
}
public Defaults getDefaults(){
return defaults;
}
public Caches getCaches()
{
if(caches == null)
synchronized(isCacheInit)
{
if(isCacheInit.equals(Boolean.FALSE))
try
{
caches = createCaches();
isCacheInit = Boolean.TRUE;
}
catch(Throwable ex)
{
throw new RuntimeException(ex);
}
}
return caches;
}
private static Defaults createDefaults(){
//读取配置文件
return null;
}
private static Caches createCaches(){
//读取配置文件
return null;
}
}
案例二、
线程池
package com.cn.javaFrame.demo.demo02.threadpool;
import java.util.LinkedList;
import java.util.List;
/**
* 线程池类,线程管理器:创建线程,执行任务,销毁线程,获取线程基本信息
* @author
*
*/
public final class ThreadPool {
//线程池中默认线程的个数为5
private static int worker_num = 5;
//工作线程
private WorkThread[] workThreads;
//未处理的任务
private static volatile int finished_task = 0;
//任务列表,作为一个缓存,List线程不安全
private List<Runnable> taskQueue = new LinkedList<Runnable>();
private static ThreadPool threadPool;
private ThreadPool(){
this(5);
}
private ThreadPool(int work_num){
ThreadPool.worker_num=work_num;
workThreads = new WorkThread[worker_num];
for(int i=0; i<work_num; i++){
workThreads[i] = new WorkThread();
//开启线程池
workThreads[i].start();
}
}
public static ThreadPool getThreadPool(){
return getTheadPool(ThreadPool.worker_num);
}
public static ThreadPool getTheadPool(int worker_num1){
if(worker_num1<=0){
worker_num1=ThreadPool.worker_num;
}
if(threadPool == null){
threadPool = new ThreadPool(worker_num1);
}
return threadPool;
}
// 执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理决定
public void execute(Runnable task) {
synchronized (taskQueue) {
taskQueue.add(task);
taskQueue.notify();
}
}
// 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器决定
public void execute(Runnable[] task) {
synchronized (taskQueue) {
for (Runnable t : task)
taskQueue.add(t);
taskQueue.notify();
}
}
// 批量执行任务,其实只是把任务加入任务队列,什么时候执行有线程池管理器决定
public void execute(List<Runnable> task) {
synchronized (taskQueue) {
for (Runnable t : task)
taskQueue.add(t);
taskQueue.notify();
}
}
// 销毁线程池,该方法保证在所有任务都完成的情况下才销毁所有线程,否则等待任务完成才销毁
public void destroy() {
while (!taskQueue.isEmpty()) {// 如果还有任务没执行完成,就先睡会吧
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 工作线程停止工作,且置为null
for (int i = 0; i < worker_num; i++) {
workThreads[i].stopWorker();
workThreads[i] = null;
}
threadPool=null;
taskQueue.clear();// 清空任务队列
}
// 返回工作线程的个数
public int getWorkThreadNumber() {
return worker_num;
}
// 返回已完成任务的个数,这里的已完成是只出了任务队列的任务个数,可能该任务并没有实际执行完成
public int getFinishedTasknumber() {
return finished_task;
}
// 返回任务队列的长度,即还没处理的任务个数
public int getWaitTasknumber() {
return taskQueue.size();
}
// 覆盖toString方法,返回线程池信息:工作线程个数和已完成任务个数
@Override
public String toString() {
return "WorkThread number:" + worker_num + " finished task number:"
+ finished_task + " wait task number:" + getWaitTasknumber();
}
/**
* 内部类,工作线程
*/
private class WorkThread extends Thread {
// 该工作线程是否有效,用于结束该工作线程
private boolean isRunning = true;
/*
* 关键所在啊,如果任务队列不空,则取出任务执行,若任务队列空,则等待
*/
@Override
public void run() {
Runnable r = null;
while (isRunning) {// 注意,若线程无效则自然结束run方法,该线程就没用了
synchronized (taskQueue) {
while (isRunning && taskQueue.isEmpty()) {// 队列为空
try {
taskQueue.wait(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (!taskQueue.isEmpty())
r = taskQueue.remove(0);// 取出任务
}
if (r != null) {
r.run();// 执行任务
}
finished_task++;
r = null;
}
}
// 停止工作,让该线程自然执行完run方法,自然结束
public void stopWorker() {
isRunning = false;
}
}
}
线程池出处:
http://blog.csdn.net/hsuxu/article/details/8985931