数据库连接池的设计思路及java实现

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

connectionPool.DBConnectionManager

[java] view plain copy

  1. package connectionPool;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.Driver;  
  5. import java.sql.DriverManager;  
  6. import java.sql.SQLException;  
  7. import java.util.ArrayList;  
  8. import java.util.Enumeration;  
  9. import java.util.HashSet;  
  10. import java.util.Hashtable;  
  11. import java.util.List;  
  12. import java.util.Map;  
  13. import java.util.Map.Entry;  
  14. import java.util.Set;  
  15.   
  16. import connectionPool.util.Logger;  
  17. import connectionPool.util.PropertiesMgr;  
  18.   
  19. /** 
  20.  * 连接池的设计思路 
  21.  * 1、 
  22.  * 初始化固定数目的连接(空闲连接与活跃连接在同一池中),建立连接的代理类,添加busy与startTime属性以便分发与回收连接 
  23.  * 另建立守护线程回收失效连接 
  24.  * 2、 
  25.  * 维护一空闲连接池,初始为空,需要连接时建立,用完的连接回收进入空闲连接池; 
  26.  * 后续所需连接从空闲连接池获取;activeNum记录活跃连接数目; 
  27.  * 当空闲连接池为空且活跃连接数达到上限时,请求等待,超时即获取连接失败,超时前有连接被释放方可获得连接 
  28.  * 第二个设计巧妙优势明显,采用第二种方式 
  29.  *  
  30.  * 数据库连接管理类,单例模式 
  31.  * 可以管理加载多个数据库驱动,维护多个数据库连接池 
  32.  * @author shijin 
  33.  * 
  34.  */  
  35. public class DBConnectionManager {  
  36.       
  37.     private static DBConnectionManager dbm = null;  
  38.       
  39.     //单例模式里的成员变量都相当于是static了?  
  40.     /** 
  41.      * 客户数目 
  42.      */  
  43.     private static int clients = 0;  
  44.     /** 
  45.      * 加载的驱动器集合 
  46.      */  
  47.     private Set<Driver> drivers = new HashSet<Driver>();  
  48.     /** 
  49.      * 数据库连接池字典 
  50.      */  
  51.     private Hashtable<String,DBConnectionPool> pools = new Hashtable<String,DBConnectionPool>();  
  52.       
  53.     private final Logger log = Logger.getInstance(DBConnectionPool.class);  
  54.       
  55.     private DBConnectionManager() {  
  56.         loadDrivers();  
  57.         createPools();  
  58.     }  
  59.   
  60.     /** 
  61.      * 装载和注册所有的JDBC驱动程序 
  62.      */  
  63.     private void loadDrivers() {  
  64.         String str_drivers = PropertiesMgr.getProperty("driver");  
  65.         for(String str_driver:str_drivers.split("\\s")) {  
  66.             Driver driver = null;  
  67.             try {  
  68.                 driver = (Driver)Class.forName(str_driver).newInstance();  
  69.                 DriverManager.registerDriver(driver);  
  70.                 log.info("成功加载JDBC驱动:" + str_driver);  
  71.             } catch (InstantiationException e) {  
  72.                 log.error("加载JDBC驱动" + str_driver + "时初始化异常,请检查配置文件");  
  73.             } catch (IllegalAccessException e) {  
  74.                 log.info("加载JDBC驱动" + str_driver + "时非法访问,请检查配置文件");  
  75.             } catch (ClassNotFoundException e) {  
  76.                 log.info("未找到JDBC驱动" + str_driver + "请引入相关包");  
  77.             } catch (SQLException e) {  
  78.                 log.info("加载JDBC驱动" + str_driver + "失败,请检查引入包的正确性");  
  79.             }  
  80.             drivers.add(driver);  
  81.         }  
  82.     }  
  83.   
  84.     /** 
  85.      * 根据配置文件创建数据库连接池 
  86.      */  
  87.     private void createPools() {  
  88.         Enumeration<?> elements = PropertiesMgr.propertiesNames();  
  89.         while(elements.hasMoreElements()) {  
  90.             String element = (String)elements.nextElement();  
  91.             if(element.endsWith(".url")) {  
  92.                 String poolName = element.substring(0, element.lastIndexOf("."));  
  93.                 String url = PropertiesMgr.getProperty(poolName + ".url");  
  94.                 if(url == null) {  
  95.                     log.error("无法连接到数据库" + poolName + "请检查配置文件连接字符串");  
  96.                     continue;  
  97.                 }  
  98.                 String user = PropertiesMgr.getProperty(poolName + ".user");  
  99.                 String pwd = PropertiesMgr.getProperty(poolName + ".password");  
  100.                 String str_max = PropertiesMgr.getProperty(poolName + ".maxconn", "0");  
  101.                 int maxConn = 0;  
  102.                 try{  
  103.                     maxConn = Integer.parseInt(str_max);  
  104.                 }catch(NumberFormatException e) {  
  105.                     log.error("数据库" + poolName + "最大连接数设置错误,默认设为20");  
  106.                     maxConn = 20;  
  107.                 }                 
  108.                 DBConnectionPool pool = new DBConnectionPool(maxConn,url,poolName,user,pwd);  
  109.                 pools.put(poolName, pool);  
  110.                 log.info("成功创建数据库连接池" + poolName);  
  111.             }  
  112.         }  
  113.     }  
  114.   
  115.     /** 
  116.      * 获得单例 
  117.      * @return DBConnectionManager单例 
  118.      */  
  119.     public synchronized static DBConnectionManager getInstance() {  
  120.         if(dbm == null) {  
  121.             dbm = new DBConnectionManager();  
  122.         }  
  123.         clients++;  
  124.         return dbm;  
  125.     }  
  126.   
  127.     /** 
  128.      * 从指定连接池中获取可用连接,无等待 
  129.      * @param poolName  要获取连接的连接池名称 
  130.      * @return  连接池中的一个可用连接或null 
  131.      */  
  132.     public Connection getConnection(String poolName) {  
  133.         DBConnectionPool pool = (DBConnectionPool)pools.get(poolName);  
  134.         return pool.getConnection();  
  135.     }  
  136.       
  137.     /** 
  138.      * 从指定的连接池获取可用连接,有等待超时 
  139.      * @param poolName  要获取连接的连接池名称 
  140.      * @param timeout   获取可用连接的超时时间,单位为秒 
  141.      * @return          连接池中的一个可用连接或null 
  142.      */  
  143.     public Connection getConnection(String poolName,long timeout) {  
  144.         DBConnectionPool  pool = (DBConnectionPool)pools.get(poolName);  
  145.         return pool.getConnection(timeout);  
  146.     }  
  147.       
  148.     /** 
  149.      * 回收指定连接池的连接 
  150.      * @param poolName  连接池名称 
  151.      * @param conn      要回收的连接 
  152.      */  
  153.     public void freeConnection(String poolName,Connection conn) {  
  154.         DBConnectionPool pool = (DBConnectionPool)pools.get(poolName);  
  155.         if(pool != null) {  
  156.             pool.freeConnection(conn);  
  157.         }  
  158.         log.error("找不到连接池,无法回收,请检查参数");  
  159.     }  
  160.       
  161.     /** 
  162.      * 关闭所有连接,撤销驱动器的注册 
  163.      */  
  164.     public synchronized void release() {  
  165.         //所有客户连接都关闭时才真正关闭连接撤销注册  
  166.         if(clients-- != 0) {  
  167.             return;  
  168.         }  
  169.         for(Map.Entry<String,DBConnectionPool> poolEntry:pools.entrySet()) {  
  170.             DBConnectionPool pool = poolEntry.getValue();  
  171.             pool.releaseAll();  
  172.         }  
  173.         log.info("已经关闭所有连接");  
  174.         for(Driver driver:drivers) {  
  175.             try {  
  176.                 DriverManager.deregisterDriver(driver);  
  177.                 log.info("撤销JDBC驱动器" + driver.getClass().getName() + "的注册");  
  178.             } catch (SQLException e) {  
  179.                 log.error("撤销JDBC驱动器" + driver.getClass().getName() + "的注册异常");  
  180.             }  
  181.         }  
  182.         log.info("驱动器撤销完成");  
  183.     }  
  184.       
  185.     /** 
  186.      * 此内部类定义了一个连接池. 
  187.      * 它能够获取数据库连接,直到预定的最 大连接数为止 
  188.      * 在返回连接给客户程序之前,它能够验证连接的有效性 
  189.      * @author shijin 
  190.      */  
  191.     private class DBConnectionPool {  
  192.         private int activeNum = 0;  
  193.         private int maxConn = 0;  
  194.         private String url = null;  
  195.         private String poolName = null;  
  196.         private String user = null;  
  197.         private String pwd = null;  
  198.         private List<Connection> freeConnections = new ArrayList<Connection>();  
  199.           
  200.         /** 
  201.          *  
  202.          * @param maxConn   设定的连接池允许的最大连接数 
  203.          * @param url       数据库连接url 
  204.          * @param poolName  连接池名称 
  205.          * @param user      数据库用户名,或null 
  206.          * @param pwd       数据库用户密码,或null 
  207.          */  
  208.         public DBConnectionPool(int maxConn, String url, String poolName,  
  209.                 String user, String pwd) {  
  210.             super();  
  211.             this.maxConn = maxConn;  
  212.             this.url = url;  
  213.             this.poolName = poolName;  
  214.             this.user = user;  
  215.             this.pwd = pwd;  
  216.         }  
  217.           
  218.         /** 
  219.          * 获得一个可用连接,不保证任何情况都能返回一个连接(比如超过最大连接数的时候返回null) 
  220.          * 1、若空闲连接池不为空,从空闲连接池取出一个连接后检查有效性,正常则返回,失效则重新获取连接 
  221.          * 2、若空闲连接池为空且未超过最大连接数限制,新建一个连接并返回 
  222.          * 3、空闲连接数为空且超过最大连接数限制,返回null 
  223.          * @return  获得的可用连接 
  224.          */  
  225.         public synchronized Connection getConnection() {  
  226.             Connection conn = null;  
  227.             //空闲连接池中有空闲连接,直接取  
  228.             if(freeConnections.size() > 0) {  
  229.                 //从空闲连接池中取出一个连接  
  230.                 conn = freeConnections.get(0);  
  231.                 freeConnections.remove(0);  
  232.                 //检测连接有效性  
  233.                 try{  
  234.                     if(conn.isClosed()) {  
  235.                         //由于已经从空闲连接池取出,所以不使用无效连接其就无法重新进入  
  236.                         //空闲连接池,意味着其已经被删除了,记入日志即可  
  237.                         log.info("从连接池" + poolName + "中取出的连接已关闭,重新获取连接");  
  238.                         //继续从连接池尝试获取连接  
  239.                         conn = getConnection();  
  240.                     }  
  241.                 }catch(SQLException e) {  
  242.                     log.info("从连接池" + poolName + "中取出的发生服务器访问错误,重新获取连接");  
  243.                     conn = getConnection();  
  244.                 }  
  245.             } else if(activeNum < maxConn) {  
  246.                 conn = newConnection();  
  247.             } else {  
  248.                 //未获得连接  
  249.             }  
  250.             if(conn != null) {  
  251.                 activeNum++;  
  252.             }  
  253.             return conn;  
  254.         }  
  255.           
  256.         /** 
  257.          * 当无空闲连接而又未达到最大连接数限制时创建新的连接 
  258.          * @return  新创建的连接 
  259.          */  
  260.         private Connection newConnection() {  
  261.             Connection conn = null;  
  262.             try{  
  263.                 if(user == null) {  
  264.                     conn = DriverManager.getConnection(url);  
  265.                 } else {  
  266.                     conn = DriverManager.getConnection(url, user, pwd);  
  267.                 }  
  268.                 log.info("与数据库" + poolName + "创建一个新连接");  
  269.             }catch(SQLException e) {  
  270.                 log.error("无法根据\"" + url + "\"与数据库" + poolName + "建立新连接");  
  271.             }  
  272.             return conn;  
  273.         }  
  274.           
  275.         /** 
  276.          * 获得一个可用连接,超过最大连接数时线程等待,直到有有连接释放时返回一个可用连接或者超时返回null 
  277.          * @param timeout 等待连接的超时时间,单位为秒 
  278.          * @return 
  279.          */  
  280.         public synchronized Connection getConnection(long timeout) {  
  281.             Connection conn = null;  
  282.             long startTime = System.currentTimeMillis();  
  283.             while((conn = getConnection()) == null) {  
  284.                 try{  
  285.                     //被notify(),notifyALL()唤醒或者超时自动苏醒  
  286.                     wait(timeout);  
  287.                 }catch(InterruptedException e) {  
  288.                     log.error("等待连接的线程被意外打断");  
  289.                 }  
  290.                 //若线程在超时前被唤醒,则不会返回null,继续循环尝试获取连接  
  291.                 if(System.currentTimeMillis() - startTime > timeout*1000000)  
  292.                     return null;  
  293.             }  
  294.             return conn;  
  295.         }  
  296.           
  297.         /** 
  298.          * 将释放的空闲连接加入空闲连接池,活跃连接数减一并激活等待连接的线程 
  299.          * @param conn  释放的连接 
  300.          */  
  301.         public synchronized void freeConnection(Connection conn) {  
  302.             freeConnections.add(conn);  
  303.             activeNum--;  
  304.             notifyAll();//通知正在由于达到最大连接数限制而wait的线程获取连接  
  305.         }  
  306.           
  307.         /** 
  308.          * 关闭空闲连接池中的所有连接 
  309.          */  
  310.         public synchronized void releaseAll() {  
  311.             for(Connection conn:freeConnections) {  
  312.                 try{  
  313.                     conn.close();  
  314.                     log.info("关闭空闲连接池" + poolName + "中的一个连接");  
  315.                 }catch(SQLException e) {  
  316.                     log.error("关闭空闲连接池" + poolName + "中的连接失败");  
  317.                 }  
  318.             }  
  319.             freeConnections.clear();  
  320.         }  
  321.     }  
  322. }  

connectionpool.util.Logger

[java] view plain copy

  1. package connectionPool.util;  
  2.   
  3. import java.io.FileWriter;  
  4. import java.io.IOException;  
  5. import java.io.PrintWriter;  
  6. import java.util.Date;  
  7.   
  8. /** 
  9.  * 日志文件创建维护类,单例模式 
  10.  * @author shijin 
  11.  * 
  12.  */  
  13. public class Logger {  
  14.       
  15.     private static Logger logger= null;  
  16.     private PrintWriter log = null;  
  17.     private static int level = 0;  
  18.     private Class<?> c = null;  
  19.     private static final int DEBUGLEVEL = 1;  
  20.     private static final int INFOLEVEL = 2;  
  21.     private static final int ERRORLEVEL = 3;  
  22.       
  23.     private Logger(Class<?> c) {  
  24.         String logFileName = PropertiesMgr.getProperty("logfile","DBlog.txt");  
  25.         String str_level = PropertiesMgr.getProperty("loglevel", "3");  
  26.         this.c = c;  
  27.         level = Integer.parseInt(str_level);  
  28.         try {  
  29.             log = new PrintWriter(new FileWriter(logFileName),true);  
  30.         } catch (IOException e) {  
  31.             System.err.println("无法打开日志文件" + logFileName);  
  32.             log = new PrintWriter(System.err);  
  33.         }  
  34.     }  
  35.       
  36.     public synchronized static Logger getInstance(Class<?> c) {  
  37.         if(logger == null) {  
  38.             logger = new Logger(c);  
  39.         }  
  40.         return logger;  
  41.     }  
  42.       
  43.       
  44.     public void debug(String msg) {  
  45.         if(level > DEBUGLEVEL) {  
  46.             msg = "DEBUG:" + new Date() + "-" + msg;  
  47.             System.out.println(msg);  
  48.             log.println(msg);  
  49.         }  
  50.               
  51.     }  
  52.       
  53.     public void info(String msg) {  
  54.         if(level > INFOLEVEL) {  
  55.             msg = "INFO:" + new Date() + "-" + msg;  
  56.             System.out.println(msg);  
  57.             log.println(msg);  
  58.         }  
  59.               
  60.     }  
  61.       
  62.     public void error(String msg) {  
  63.         if(level > ERRORLEVEL) {  
  64.             msg = "ERROR:" + new Date() + "-" + c + "-" + msg;  
  65.             System.out.println(msg);  
  66.             log.println(msg);  
  67.         }  
  68.     }  
  69. }  

connection.util.PropertiesMgr

[java] view plain copy

  1. package connectionPool.util;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.util.Enumeration;  
  6. import java.util.Properties;  
  7. /** 
  8.  * 属性文件加载管理类,单例模式 
  9.  * @author shijin 
  10.  * 
  11.  */  
  12. public class PropertiesMgr {  
  13.     private static Properties pro = new Properties();  
  14.     private PropertiesMgr(){}  
  15.     static {  
  16.         try {  
  17.             pro.load(PropertiesMgr.class.getClassLoader().getResourceAsStream("config" + File.separator + "DB.properties"));  
  18.         } catch (IOException e) {  
  19.             e.printStackTrace();  
  20.         }  
  21.     }  
  22.       
  23.     public static String getProperty(String key) {  
  24.         return pro.getProperty(key);  
  25.     }  
  26.       
  27.     public static String getProperty(String key,String defaultValue) {  
  28.         //找不到key用defaultValue,而不是说后面为空字符串采用defaultValue  
  29.         return pro.getProperty(key, defaultValue);  
  30.     }  
  31.       
  32.     public static Enumeration<?> propertiesNames() {  
  33.         return pro.propertyNames();  
  34.     }  
  35. }  

DB.properties

[plain] view plain copy

  1. driver=com.mysql.jdbc.Driver  
  2.   
  3. mysql.url=jdbc:mysql://127.0.0.1/caiwu?useUnicode=true&characterEncoding=gb2312  
  4.   
  5. mysql.user=root  
  6.   
  7. mysql.password=123  
  8.   
  9. mysql.maxconn=1000  
  10.   
  11. #\u65E5\u5FD7\u6587\u4EF6\u7684\u540D\u79F0  
  12. logfile=  
  13. #\u65E5\u5FD7\u7EA7\u522B  
  14. loglevel=  

转载于:https://my.oschina.net/newchaos/blog/1555846

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540436.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

窄带物联网(NB-IoT)初步了解

哪有什么天生如此&#xff0c;只是我们天天坚持。既然总有人要赢的话&#xff0c;为什么不能是我呢&#xff1f;[TOC] 什么是NB-Iot? 基于蜂窝的窄带物联网&#xff08;Narrow Band Internet of Things, NB-IoT&#xff09;成为万物互联网络的一个重要分支。NB-IoT构建于蜂窝网…

JavaOne大事纪:IBM谈OpenJ9和Open Liberty

JavaOne大会以IBM陈述其最近对开源社区的贡献作为开场&#xff1a;OpenJ9、Open Liberty和MicroProfile。IBM杰出工程师John Duimovich做了“IBM和Java&#xff1a;助力下一代创新”的开场演讲。\\读者可以回看演讲视频。\\Duimovich说IBM之所以致力于推动Java生态系统的创新&a…

c语言格式对齐填充_C ++中类的大小 课堂上的填充和对齐| 派生类的大小

c语言格式对齐填充Prerequisite: 先决条件&#xff1a; sizeof() operator in C/C C / C 中的sizeof()运算符 Size of struct in C C中的struct大小 We know that a struct size is not only the summation of all the data members, rather its the minimum sum guaranteed. …

ELK系列~对fluentd参数的理解

这段时候一直在研究ELK框架&#xff0c;主要集成在对fluentd和nxlog的研究上&#xff0c;国内文章不多&#xff0c;主要看了一下官方的API&#xff0c;配合自己的理解&#xff0c;总结了一下&#xff0c;希望可以帮到刚入行的朋友们&#xff01; Fluentd&#xff08;日志收集与…

css 文本背景色透明_如何使用CSS将文本或图像的背景设置为透明?

css 文本背景色透明Introduction: 介绍&#xff1a; In web development, there are numerous ways by which we can style our websites or web pages. You can make use of lots of properties for creating attractive and responsive websites. 在Web开发中&#xff0c;我…

一次前端笔试总结

1.有一个长度未知的数组a&#xff0c;如果它的长度为0就把数字1添加到数组里面&#xff0c;否则按照先进先出的队列规则让第一个元素出队。 分析&#xff1a;这道题主要是考核了数组的队列方法和栈方法。另外&#xff0c;原题还有字数限制的&#xff0c;只有在字数小于30并且结…

SSL

今天遇到一位网友要求老蒋将他当前已经在使用的WDCP面板环境&#xff0c;给某个站点添加SSL证书&#xff0c;实现HTTPS网址访问。在过去的几篇文章中&#xff0c;老蒋也有分享过不少在Linux VPS中对应的WEB环境安装SSL证书的经历&#xff0c;其实总体来看都大同小异&#xff0c…

应用宝认领应用

2019独角兽企业重金招聘Python工程师标准>>> 【Android】命令行jarsigner签字和解决找不到证书链错误 1、签名失败 $jarsigner -verbose -keystore /Volumes/Study/resourcesLib/Qunero-achivements/AndroidApp/QuLordy-signed-key -signedjar ./signed_XiaomiVerif…

Squid服务日志分析

Squid服务日志分析 Apache 和 Squid 是两种著名的代理缓存软件&#xff0c;但Squid 较 Apache 而言是专门的代理缓存服务器软件&#xff0c;其代理缓存的功能强大&#xff0c;支持 HTTP/1.1 协议&#xff0c;其缓存对象也较多&#xff1b;并且 Squid 的缓存管理模块和访问控制模…

云时代 揭开性能监测战略的隐秘优势

云时代的性能监测战略 能够对各种变化做出快速响应而不偏离重心和企业发展动力&#xff0c;正逐渐成为各行各业、各种规模企业的奋斗目标。业务敏捷性通常是运营良好&#xff0c;可实现盈利的企业标志。实现这一目标意味着公司已经成功地利用业务关键型技术来提高生产率&#x…

聊聊全站HTTPS带来的技术挑战

日前写的文章里了讨论了数据传输的安全性的问题&#xff0c;最后一部分提到了通过HTTPS解决数据传输安全性的方案。那么一个新问题又来了&#xff0c;实施全站HTTPS的过程中&#xff0c;我们可能会遇到哪些技术问题?所以我今天和大家一起来算一下这个账&#xff0c;将技术成本…

4.3/4.4 磁盘分区

2019独角兽企业重金招聘Python工程师标准>>> 添加虚拟磁盘 第一步&#xff0c;选择虚拟机中的“设置” 第二步&#xff0c;选择“添加硬盘” 第三步&#xff0c;选择_SCSI &#xff08;推荐&#xff09; # 保持默认 第四步&#xff0c;选择“创建新的虚拟磁盘…

RoboMaster 2017:机器人版的「王者农药」,工程师们的竞技时代

8月6日晚&#xff0c;第十六届全国大学生机器人大赛 RoboMaster 2017机甲大师赛在华润深圳湾体育中心“春茧”体育馆举行&#xff0c;关于这个比赛的盛况已经无需赘述&#xff0c;去年雷锋网参加上届比赛时&#xff0c;报道的是「像看了一场演唱会」&#xff0c;如果用演唱会来…

【初学者必读】:前端工程师的知识体系

下图是前端工程师图解&#xff1a; 前端开发的核心是HTML CSS JavaScript。本质上它们构成一个MVC框架&#xff0c;即HTML作为信息模型&#xff08;Model&#xff09;&#xff0c;CSS控制样式&#xff08;View&#xff09;&#xff0c;JavaScript负责调度数据和实现某种展现逻…

使用Prometheus监控Cloudflare的全球网络

Matt Bostock在SRECON 2017欧洲大会的演讲中&#xff0c;介绍了如何使用Prometheus实现对CloudFlare分布于全球的架构和网络的监控。Prometheus是一种基于度量进行监控的工具&#xff0c;CloudFlare是一家CDN、DNS和DDoS防御&#xff08;Mitigation&#xff09;服务提供商。\\基…

开始吧

2019独角兽企业重金招聘Python工程师标准>>> 写C三年有余&#xff0c;在技术方面也算小有所成。准备在这里分享一些C进阶、Python、Golang技术文章。 CSDN博客地址&#xff1a; http://blog.csdn.net/godmaycry 以后博客同步更新。 转载于:https://my.oschina.net/u…

Exchange server 2013(十四)WSUS部署及组策略设置(2)

我们继续上一节未完的博客&#xff0c;继续我们的WSUS设置。[上一章节标题&#xff1a;Exchange server 2013(十四)WSUS部署及组策略设置(1) 网址&#xff1a;http://1183839.blog.51cto.com/blog/1173839/1182366] 首先单击自动审批,来修改审批规则,也就是说当wsus侦测到新的更…

用MATLAB结合四种方法搜寻罗马尼亚度假问题

选修了cs的AI课&#xff0c;开始有点不适应&#xff0c;只能用matlab硬着头皮上了&#xff0c;不过matlab代码全网仅此一份&#xff0c;倒有点小自豪。 一、练习题目 分别用宽度优先、深度优先、贪婪算法和 A*算法求解“罗马利亚度假问题”。具体地图我这里不给出了&#xff0c…

[转]Paul Adams:为社交设计

为社交设计 Strong, Weak, and Temporary Ties by Paul Adams on 2010/04/09 PS&#xff1a;作者Paul Adams Facebook全球品牌体验总监 电话和手机聚集十亿用户用了15年的时间&#xff0c;而Facebook只用了9个月。我们看到越来越多的人开始用在线社交网络&#xff0c;这种网络好…

Android Framework中的Application Framework层介绍

Android的四层架构相比大家都很清楚&#xff0c;老生常谈的说一下分别为&#xff1a; Linux2.6内核层&#xff0c;核心库层&#xff0c;应用框架层&#xff0c;应用层。我今天重点介绍一下应用框架层Framework。 Framework层为我们开发应用程序提供了非常多的API&#xff0c;我…