java深入探究11-基础加强

1. ? extends String:String 子类;? super String:String 父类

2.反射-》参数化类型表示

  ParameteredType:参数化类型表示,就是获得对象类参数如Base<T>;获取T类型

  Type:所有类型接口:参数化类型,引用类型,原始类型

  如何获得T类型通过反射:

    Type type=this.class().getGenricSuperclass();//获得运行类的父类即”参数类型“;

      ParameteredType pt=(ParameteredType)type;//强制转化为参数类型

    type[] types=pt.getActualTypeArgument();//获得参数类型的实际类型的定义:具体到具体T类型

    Class class=types[0]:就是指代具体T参数实际类

    -->之后就可以对这个实际类做处理了

  一般运用在BaseDao<T>想要处理T时用反射来做的

3.注解

  1)让编译器知道怎么做

  2)自定义注解

    步骤:1.创建注解

        public @interface Author{

          String name;

          int age;

        }

        注意:注解属性,修饰为默认或者public,不能有主体,如果属性名为value,使用时不需要value="",直接写“”

        2.使用注解

        @Author(name="Jet",age=23);@Author(23)

        当注解属性为数组,使用方法:@Author({"",""})

        3.原注解:对注解的注解

          1)设置注解的可以范围

            @Target({

              Type,Filed,method,parameter,costrutor,local_variable

            })

          2)注解的生命周期

            @Rentention(RententionPolicy.SOURCE);//源码级别有效

            @Rentention(RententionPolicy.CLASS);//字节码有效

            @Rentention(RententionPolicy.RUNTIME);运行时有效

      4获取方法上的注解

          getAnnotation(Author.class)

  3).例子:在使用BaseDao<T>时,当T类型的Bean对象,属性名和表名字不一样时,BaseDao<T>中方法 T findById(int id),就不能简单的用DbUtil中BeanHandler<T>(class,id)来封住结果集了

    解决方法:给T 添加注解:TableName,Id ,Column三个注解-》BaseDao<T>中通过反射的方式获得T中的注解信息,再进行封装返回实例对象

/**
 * 解决优化的问题:
 *       1. 当数据库表名与类名不一致、
 *    2. 字段与属性不一样、
 *    3. 主键不叫id
 *
 */
public class BaseDao<T> {

    // 当前运行类的类型
    private Class<T> clazz;
    // 表名
    private String tableName;
    // 主键
    private String id_primary;

    // 拿到当前运行类的参数化类型中实际的类型  ( BaseDao<Admin> ,  Admin.class)
    public BaseDao(){
        Type type = this.getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) type;
        Type[] types = pt.getActualTypeArguments();
        clazz = (Class<T>) types[0];

        //已经拿到:  Admin.class

        /*******1. 获取表名*******/
        Table table = clazz.getAnnotation(Table.class);
        tableName = table.tableName();

        /*******2. 获取主键字段*******/
        //获取当前运行类的所有字段、遍历、获取每一个字段上的id注解
        Field[] fs = clazz.getDeclaredFields();
        for (Field f : fs) {

            // 设置强制访问
            f.setAccessible(true);

            // 获取每一个字段上的id注解
            Id anno_id = f.getAnnotation(Id.class);

            // 判断
            if (anno_id != null) {
                // 如果字段上有id注解,当前字段(field)是主键; 再获取字段名称
                Column column = f.getAnnotation(Column.class);
                // 主键
                id_primary = column.columnName();
                // 跳出循环
                break;
            }
        }

        System.out.println("表:" + tableName);
        System.out.println("主键:" + id_primary);
    }

    public T findById(int id){
        try {
            String sql = "select * from " + tableName + " where " + id_primary +"=?";
            /*
             * DbUtils的已经封装好的工具类:BeanHandler?   属性=字段
             */
            return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public List<T> getAll(){
        try {
            String sql = "select * from " + tableName;
            return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

/**
 * 自定义结果集:封装单个Bean对象
 */
class BeanHandler<T> implements ResultSetHandler<T>{
    // 保存传入的要封装的类的字节码
    private Class<T> clazz;
    public BeanHandler(Class<T> clazz) {
        this.clazz = clazz;
    }

    // 封装结果集的方法
    @Override
    public T handle(ResultSet rs) throws SQLException {
        try {
            // 创建要封装的对象  ‘1’
            T t = clazz.newInstance();
            // 向下读一行
            if (rs.next()) {

                // a. 获取类的所有的Field字段数组
                Field[] fs = clazz.getDeclaredFields();

                // b. 遍历, 得到每一个字段类型:Field
                for (Field f : fs) {

                    // c. 获取”属性名称“
                    String fieldName = f.getName();

                    // e. 获取Field字段上注解   【@Column(columnName = "a_userName")】
                    Column column =  f.getAnnotation(Column.class);

                    // f. ”字段名“
                    String columnName = column.columnName();        // 数据库中字段 a_userName

                    // g. 字段值
                    Object columnValue = rs.getObject(columnName);

                    // 设置(BeanUtils组件)
                    BeanUtils.copyProperty(t, fieldName, columnValue);
                }
            }
            return t;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * 自定义结果集:封装多个Bean对象到List集合
 */
class BeanListHandler<T> implements ResultSetHandler<List<T>>{

    // 要封装的单个对象
    private Class<T> clazz;
    public BeanListHandler(Class<T> clazz){
        this.clazz = clazz;
    }

    // 把从数据库查询到的没一行记录,封装为一个对象,再提交到list集合, 返回List<T>
    @Override
    public List<T> handle(ResultSet rs) throws SQLException {
        List<T> list = new ArrayList<T>();
        try {
            // 向下读一行
            while (rs.next()) {

                // 创建要封装的对象  ‘1’
                T t = clazz.newInstance(); 

                // a. 获取类的所有的Field字段数组
                Field[] fs = clazz.getDeclaredFields();

                // b. 遍历, 得到每一个字段类型:Field
                for (Field f : fs) {

                    // c. 获取”属性名称“
                    String fieldName = f.getName();

                    // e. 获取Field字段上注解   【@Column(columnName = "a_userName")】
                    Column column =  f.getAnnotation(Column.class);

                    // f. ”字段名“
                    String columnName = column.columnName();        // 数据库中字段 a_userName

                    // g. 字段值
                    Object columnValue = rs.getObject(columnName);

                    // 设置(BeanUtils组件)
                    BeanUtils.copyProperty(t, fieldName, columnValue);
                }
                // 对象添加到集合
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

4.日志log4j:开源日志组件

  使用步骤:

    1.下载组件:log4j-1.2.11.jar
    2.配置src/log4.properties
      日志输出优先级:debug<info<warn<error
    3.使用
      Log log=LogFactory.getLog(App.class);
      log.info("信息提示");log.debug("调试信息");
      log.warn("警告提示");log.error(“异常提示”)
    4.log4.properties的配置详解
      1)通过根元素指定日志输出级别、目的地
        log4j.rootLogger=info,console,file
      2)日志输出到console配置
        //日志输出到控制台使用的api
        log4j.appender.console==org.apache.log4j.ConsoleAppender
        //日志输出格式:灵活的格式
        log4j.appender.console.layout=org.apache.log4j.PatterLayout
        //具体的格式内容
        Log4.appender.console.Layout.ConversionPattern=%d %p %c.%M()-%m%n
      日志输出到文件
        log4j.appender.file=org.apache.log4j.RollingFileAppender
        # 文件参数: 指定日志文件路径
        log4j.appender.file.File=../logs/MyLog.log
        # 文件参数: 指定日志文件最大大小
        log4j.appender.file.MaxFileSize=5kb
        # 文件参数: 指定产生日志文件的最大数目
        log4j.appender.file.MaxBackupIndex=100
        # 日志格式
        log4j.appender.file.layout=org.apache.log4j.PatternLayout
        log4j.appender.file.layout.ConversionPattern=%d %c.%M()-%m%n

    

 

使用Log4J进行日志操作

 

Log4J简介

 

Log4J是Apache的一个开放源代码项目,它是一个日志操作包,通过使用Log4J,可以指定日志信息输出的目的地,如控制台、文件、CUI组件、NT的事件记录器;还可以控制每一条日志输出格式。此外,通过定义日志信息的级别,能够非常细致地控制日志的输出,最令人感兴趣的是,这些功能可以通过一个配置文件来灵活进行配置,而不需要修改应程序代码。

在应用程序中输出日志有3个目的:

l 监视代码中变量的变化情况,把数据周期性记录到文件中供其他应用进行统计分析工作

l 跟踪代码运行时轨迹,作为日后审计的依据

l 担当集成开发环境中的调试器的作用,向文件和控制台打印代码的调试信息

要在程序中输出日志,最普通的做法就是在代码中嵌入语句,这些打印语句可以把日志输出到控制台或文件中,比较好的做法就是构造一个日志操作类来封装此类操作,而不是让一系列的打印语句充斥代码的主体。

 

在强调可重用组件的今天,除了自己从头到尾开发一个可重用的日志操作类名,Apache为我们提供了一个强有力的现成的日志操作包Log4J。

Log4J主要由三大组件构成:

l Logger:负责生成日志,并能够对日志信息进行分类筛选,通俗地讲就是决定什么日志信息应该输出,什么日志信息应该被忽略

l Appender:定义了日志信息输出的目的地,指定日志信息应该被输出到什么地方,这些地方可以是控制台、文件、网络设备等

l Layout: 指定日志信息的输出格式

这个3个组件协同工作,使得开发者能够依据日志信息类别记录信息,并能够在程序运行期间,控制日志信息的输出格式以及日志存放地点。

一个Logger可以有多个Appender,这意味着日志信息可以同时输出到多个设备上,每个Appender都对应一种Layout,Layout决定了输出日志信息的格式。

假定根据实际需要,要求程序中的日志信息既能输出到程序运行的控制台下,又能输出到指定的文件中,并且当日志信息输出到控制台时SimplLayout布局,当日志信息输出到文件时PatternLayout布局,此时Logger、Appender和Layout3个组件的关系如图  

 

 

Appender组件 (指定输出目的)
Log4J的Appender组件决定将日志信息输出到什么地方。日前Log4J的Appender支持将日志信息输出到以下的目的:

l 控制台(Console)

l 文件

l GUI组件

一个logger可以同时对应多个Appender,也就是说,一个Logger的日志信息可以同时输出到多个目的地,例如:要为rootLogger配置两个Appender; 一个是file,一个是console,则可以采用如下配置代码:
   


log4j.rootLogger =WARN,file,console          rootLogger  配置日志级别、输出目的;

log4j.appender.file=org.apache.log4jRollingFileAppender
    log4j.appender.file=log.txt

log4j.appender.console=org.apache.log4j.ConsoleAppender

 Layout组件
Layout组件用来决定日志的输出格式,它有以下几种类型

l org.apache.log4j.HTMLLayout(以HTML表格形式布局)

l org.apache.log4j.PatternLayout(可以灵活地指定布局模式)

l org.apache.log4j.SimpleLayout(包含日志信息级别和信息字符串)

l org.apache.log4j.TTCCLayout(包含日志产生的时间、线程和类别等信息)

Log4j的基本使用方法

在应用程序中使用Log4J,首先在一个配置文件中配置Log4j的各个组件,然后就可以在程序中通过Log4JAPI来操作日志

定义配置文件
Log4J由3个重要的组件构成:Logger、Appender和layout。Log4J支持在程序中以编程的方式设置这些组件,还支持通过配置文件来配置组件,后一种方式更为灵活。

Log4J支持两种配置文件格式,一种是XML格式,一种是Java属性文件,

1. 配置Logger组件
其语法为:
      log4j.rootLogger = [ level ] , appenderName1, appenderName2, …

举例:

log4j.rootLogger =WARN,file,console

level : 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。

Log4j建议只使用四个级别,优先级从高到低分别是ERROR>WARN>INFO>DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。

appenderName:就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

All:打印所有日志。

Off:关闭所有的日志。
     例如:log4j.rootLogger=info,A1,B2,C3

2. 配置Appender组件

 

其语法为:
     log4j.appender.appenderName =fully.qualified.name.of.appender.class.

举例:

log4j.appender.console=org.apache.log4j.ConsoleAppender


    "fully.qualified.name.of.appender.class" 可以指定下面五个目的地中的一个
          1.org.apache.log4j.ConsoleAppender(控制台)
          2.org.apache.log4j.FileAppender(文件) 【只能把日志输出一个文件,不推荐】
          3.org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
          4.org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
          5.org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

 

A.ConsoleAppender选项
    Threshold=WARN:指定日志消息的输出最低层次。
     ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
     Target=System.err:默认情况下是:System.out,指定输出控制台
B.FileAppender 选项

Threshold=WARN:指定日志消息的输出最低层次。

ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。

File=mylog.txt:指定消息输出到mylog.txt文件。
     Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖

指定的文件内容。
C.DailyRollingFileAppender 选项
      Threshold=WARN:指定日志消息的输出最低层次。
       ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
       File=mylog.txt:指定消息输出到mylog.txt文件。
       Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指定

的文件内容。
      DatePattern=‘.‘yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。当然也可

以指定按月、周、天、时和分。即对应的格式如下:
                    1)‘.‘yyyy-MM: 每月
                    2)‘.‘yyyy-ww: 每周
                    3)‘.‘yyyy-MM-dd: 每天
                    4)‘.‘yyyy-MM-dd-a: 每天两次
                    5)‘.‘yyyy-MM-dd-HH: 每小时
                    6)‘.‘yyyy-MM-dd-HH-mm: 每分钟
D.RollingFileAppender 选项
           Threshold=WARN:指定日志消息的输出最低层次。
            ImmediateFlush=true:默认值是true,意谓着所有的消息都会被立即输出。
            File=mylog.log:指定消息输出到mylog.txt文件。
            Append=false:默认值是true,即将消息增加到指定文件中,false指将消息覆盖指

定的文件内容。
            MaxFileSize=100KB: 后缀可以是KB, MB 或者是 GB. 在日志文件到达该大小

时,将会自动滚动,即将原来的内容移到mylog.log.1文件。
            MaxBackupIndex=2:指定可以产生的滚动文件的最大数。

3、配置日志信息的格式

其语法为:
  1)log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
         "fully.qualified.name.of.layout.class" 可以指定下面4个格式中的一个

举例:log4j.appender.console.layout=org.apache.log4j.PatternLayout

      log4j.appender.console.layout.ConversionPattern=%d %p %c.%M()-%m%n

1.org.apache.log4j.HTMLLayout(以HTML表格形式布局)包含选项:

LocationInfo=true:默认值是false,输出java文件名称和行号
                      Title=my app file: 默认值是 Log4J Log Messages.

         2.org.apache.log4j.PatternLayout(可以灵活地指定布局模式)包含选项:

ConversionPattern=%m%n :指定怎样格式化指定的消息。

         3.org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
         4.org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
        2)log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %d{yyyy-MM-dd HH:mm:ssS} %c %m%n
      日志信息格式中几个符号所代表的含义:
   -X号: X信息输出时左对齐;
         %p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
         %d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:  %d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
         %r: 输出自应用启动到输出该log信息耗费的毫秒数
        %c: 输出日志信息所属的类目,通常就是所在类的全名
         %t: 输出产生该日志事件的线程名
         %l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程, 以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
         %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
        %%: 输出一个"%"字符
        %F: 输出日志消息产生时所在的文件名称
        %L: 输出代码中的行号
        %m: 输出代码中指定的消息,产生的日志具体信息
        %n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行

%M  代表方法的名字
         可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
         1)%20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20。
          2)%-20c:指定输出category的名称,最小的宽度是20,如果category的名称小于20的话,"-"号指定左对齐。
          3)%.30c:指定输出category的名称,最大的宽度是30,如果category的名称大于30的话,就会将左边多出的字符截掉,但小于30的话也不会有空格。
           4)%20.30c:如果category的名称小于20就补空格,并且右对齐,如果其名称长于30字符,就从左边交远销出的字符截掉。

在程序中访问Log4J,需要用到Log4J的JAR文件。
在程序中使用Log4J包含以下过程:

l 获得日志记录器

l 读取配置文件,配置Log4J环境

l 输出日志信息

在进入学习Log4J之前,我们要了解通用日志包中的两个常用接口LogFactory和Log,下面分别介绍它们的用法。

Log接口

通用日志包把日志消息分为6种级别:FATAL(致命的)、ERROR(错误)、WARN(警告)、INFO(信息)、DEBUG(调试)和TRACE(细节)。其中FATAL级别最高,TRACE级别最低。通用日志包采用日志级别机制,可以灵活的控制输出的日志内容。

org.apache.commons.logging.Log接口代表日志器,它提供了一组输出日志的方法:

l fatal(Object message): 输出FATAL级别的日志消息。

l error(Object message): 输出ERROR级别的日志消息。

l ……

l trace(Object message): 输出TRACE级别的日志消息。

对于以上输出日志的方法,只有当它输出日志的级别大于或等于为日志其配置的日志级别时,这个方法才会被真正执行。例如,如果日志器的日志级别为WARN,那么在程序中,它的fatal()、error()和warn()方法会被执行,而info()、debug()和trace()方法不会被执行

Log接口还提供了一组判断是否允许输出特定级别的日志消息的方法:

l isFatalEnabled()

l isErrorEnabled()

l ……

l isTraceEnabled()

在程序输出某种级别的日志消息之前,提倡先调用以上方法来判断该级别的日志是否允许输出,这有助于提高应用的性能。例如以下代码先把日志消息添加到StringBuffer中,最后在调用日志器的debug()方法输出日志:

StringBuffer buf = new StringBuffer();

buf.append(“Login Successsul - ”);

buf.append(“Name:”);

buf.append(username);

log.debug(buf.toString());

对于以上代码,如果日志器实际上不允许输出DEBUG级别的日志,那么执行日志器的debug()方法不会输出任何消息,此时向StringBuffer中添加消息的一大串操做都将是多余的。为了提高性能,可以合理的使用isDebugEnabled()方法,避免应用执行多余的操作:

if(log.isDebugEnabled){

StringBuffer buf = new StringBuffer();

buf.append(“Login Successsul - ”);

buf.append(“Name:”);

buf.append(username);

log.debug(bug.toString());

}

(二)LogFactory接口

org.apache.commons.logging.LogFactory接口提供了获得日志器实例的两个静态方法:

public static Log getLog(String name)throws LogConfigurationException;

public static Log getLog(Class class) throws LogConfigurationException;

第一个getLog()方法以name参数作为日志器的名字;第二个getLog()方法以class参数指定的类的名字作为日志器的名字,以下是第二个getLog()方法的一种实现方式:

public static Log getLog(Class class) throws LogConfigurationException{

getLog(class.getName);     //call getLog(String name)

}

小结

Log4J主要由3大组件构成:Logger、Appender和Layout。Logger控制日志信息的输出;Appender决定日志信息的输出目的地;Layout决定日志信息的输出格式。Log4J允许用户在配置文件中灵活地配置这些组件。在程序中使用Log4J非常方便,只要先取得日志记录器,然后读取配置文件并配置Log4J环境,接下来就可以在程序中任何需要输出日志的地方,调用Logger类的适当方法来生成日志。

  

时间: 2024-11-10 13:01:31

java深入探究11-基础加强的相关文章

JAVA多线程和并发基础面试问答【转】

JAVA多线程和并发基础面试问答 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单 一进程.线程可以被称为轻量

[基础] Java目录(摘自Java核心技术·卷1 基础知识)

Java核心技术·卷1 基础知识(原书第9版) 第1章 Java程序设计概述 1.1 Java程序设计平台 1.2 Java"白皮书"的关键术语 1.2.1 简单性 1.2.2 面向对象 1.2.3 网络技能 1.2.4 健壮性 1.2.5 安全性 1.2.6 体系结构中立 1.2.7 可移植性 1.2.8 解释型 1.2.9 高性能 1.2.10 多线程 1.2.11 动态性 1.3 Java applet与Internet 1.4 Java发展简史 1.5 关于Java的常见误解

Java笔记(11)

day1 -- day3 XML Java基础加强 day4 -- day7 Servlet编程 day8 -- day10 JSP 综合案例 day11 -- day16 MySQL 数据库 练习SQL语句 JDBC编程 关系化数据模型? 常见关系化数据库有哪些? 收费产品 免费产品 Microsoft SQL Server : 微软公司产品,中等规模数据库 收费产品,运行在windows平台上 --- .net平台+SQLServer进行开发 Oracle :甲骨文公司产品,大型商业数据层,

Java(Android)线程池---基础篇

1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? 1 newThread(newRunnable(){ 2 3 @Override 4 publicvoidrun(){ 5 // TODO Auto-generated method stub 6 } 7 }).start(); 那你就out太多了,new Thread的弊端如下: a. 每次new Thread新建对象性能差.b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致

17、JAVA多线程和并发基础面试问答

JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/ 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(se

Java多线程完整版基础知识

Java多线程完整版基础知识 (翟开顺由厚到薄系列) 1.前言 线程是现代操作系统中一个很重要的概念,多线程功能很强大,java语言对线程提供了很好的支持,我们可以使用java提供的thread类很容易的创建多个线程.线程很不难,我对之前学习过的基础,在这做了一个整理,本文主要参考的是Java研究组织出版的j2se进阶和张孝祥-java就业培训教材这两本书 2.概述 2.1线程是什么 主要是线程与进程的区别,这里不再阐述,自行网上搜索 为什么使用线程:操作系统切换多个线程要比调度进程在速度上快很

java面试题大全-基础方面

Java基础方面: 1.作用域public,private,protected,以及不写时的区别答:区别如下:作用域           当前类       同一package  子孙类       其他packagepublic            √              √                  √             √protected        √              √                  √             ×friendly

Java回顾之Spring基础

第一篇:Java回顾之I/O 第二篇:Java回顾之网络通信 第三篇:Java回顾之多线程 第四篇:Java回顾之多线程同步 第五篇:Java回顾之集合 第六篇:Java回顾之序列化 第七篇:Java回顾之反射 第八篇:Java回顾之一些基础概念 第九篇:Java回顾之JDBC 第十篇:Java回顾之ORM框架 我计划分两到三篇文章来描述Spring,这一篇主要讲Spring一些基础的内容. 概述 我印象4.5年前,我还做java开发的时候,Spring是一个非常火的框架,尤其是在Web开发领域

Java NIO 网络编程基础

Java NIO提供了一套网络api,可以用来处理连接数很多的情况.他的基本思想就是用一个线程来处理多个channel. 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899

[转] JAVA多线程和并发基础面试问答

JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-answers/ 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一.在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题.(校对注:非常赞同这个观点) Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(se