- 浏览: 598882 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
ls1259775:
写的太好了,通俗易懂。
Spring之aop入门实例 -
王庆波-行:
逻辑好清晰,学习了,感谢分享!
关于web.xml中的<welcome-file-list>中的默认首页文件 -
netwelfare:
文章写的不错,不过还有一些东西没有讲解到。可以看这篇文章:Ht ...
HttpClient使用Post和Get提交参数 -
zglxx2004:
感谢!
Eclipse里maven的project报Unbound classpath variable: 'M2_REPO/**/***/***.jar -
没有这个名字:
博主,可以注释一下吗?
HttpClient模仿浏览器cookie请求需要登陆验证的页面
Java基础
基本类型不是new出来的则是放在栈里面,对象的引用也是放在栈里面的,只要是用new()来新建对象的,都会在堆中创建
String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象 o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。
值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!
java内存泄露的两个条件:无用,无法回收。
BigInteger能表示任意精度的整数, BigDecimal能表示任意精度的浮点数, 但都是用精度换速度的做法
容器集合
List的子类里面LinkedList和ArrayList是非同步的,而Vector和Stack是同步的, LinkedList底层采用的是双向链表(前指针+数据+后指针), 因此查询效率低, 增删效率高; ArrayList底层采用的是Array,因此查询效率高, 增删效率低; Vecotr是重量级的List, 一般在并发保证线程安全时采用
如果想跟踪添加给HashSet的元素的顺序,LinkedHashSet实现会有帮助。LinkedHashSet的迭代器按照元素的插入顺序来访问各个元素。
List中的元素有顺序, 可重复, Set中的元素无序, 不可重复(SortedSet是有序的)
Iterator的next方法将跳到下一个元素, 并返回刚刚跳过的元素, 因此使用remove方法的时候,必须先调用next方法
在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
LinkedHashMap扩展HashMap,以插入顺序将关键字/值对添加进链接哈希映像中。
Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。
效率
在方法内部频繁存取变量的时候, 使用局部变量比使用实例变量和静态变量要有更高的效率
异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。
I/O
任何有能力产生数据流(源)的java io对象就可以看作是一个InputStream对象, 何有能力接收数据源(流)的java io对象我们就可以看作是一个OutputStream对象
io数据流有两种类别,一种就是InputStream/OutputStream,一种是Reader/Writer, 分别用来处理字节流和字符流, 字符也是一种字节, 为什么还要用Reader/Writer呢, 这是因为在处理字符的时候可能涉及到转码,转码主要是Reader与InputStream,以及Writer与OutputStream之间, 转码的过程都是通过InputStreamReader和OutputStreamWriter来做的, 有时候我们可能没有显式的调用这两个类, 但是相关的类在内部是做了这种转换的, 比如FileReader其实就是通过InputStreamReader将数据从FileInputStream取过来的, 比如将操作系统的文字编码转化为Unicode(因为在Java内部都是采用Unicode来保存数据的), 记住这里有一个前提,那就是操作系统当前的编码格式和文档的编码格式是一直的,如果不一致就必须指定当前的InputStream的编码格式.如果不知道字符所采用何种编码方式, 那么就不要使用Reader和Writer而应该改用InputStream和OutStream
对输入/输出流进行缓冲可以提高代码执行效率, 也就是使用BufferedXxxx和BufferedXxxx对原有的流进行封装, 缓冲是一个非常重要而基本的加速I/O访问的技术
final关键字修饰的变量,表明该变量是不变的, 但是这里的不变只是所引用本身不变, 至于引用的对象是否改变则没有约束, 比如final StringBuffer a=new StringBuffer("immutable");a.append(" broken!"); //编译通过, 这里我们可以看出, final只对引用的"值"(也就是它所指向的那个对象的内存地址)有效, 它迫使引用只能指向初始指向的那个对象, 改变它的指向会导致编译器错误, 至于它所指向的对象的变化, final是不负责的.
当你要clone的类里面含有可修改的引用字段的时候,那么你一定要把整个类的蓝图进行复制,如果对你clone得到的对象进行修改的时候还会影响到原来的实例,那么这是不可取的。所以应该这样clone()
JVM
一般来说,我们使用虚拟机的类装载时需要继承抽象类java.lang.ClassLoader,其中必须实现的方法是loadClass(),对于这个方法需要实现如下操作:(1) 确认类的名称;(2) 检查请求要装载的类是否已经被装载;(3) 检查请求加载的类是否是系统类;(4) 尝试从类装载器的存储区获取所请求的类;(5) 在虚拟机中定义所请求的类;(6) 解析所请求的类;(7) 返回所请求的类。
Java中的类的装载过程也就是代理装载的过程。比如:Web浏览器中的JVM需要装载一个小应用程序TestApplet。JVM调用小应用程序装载器ACL(Applet ClassLoader)来完成装载。ACL首先请求它的父装载器, 即系统装载器装载TestApplet是否装载了这个类, 由于TestApplet不在系统装载器的装载路径中, 所以系统装载器没有找到这个类, 也就没有装载成功。接着ACL自己装载TestApplet。ACL通过网络成功地找到了TestApplet.class 文件并将它导入到了JVM中。在装载过程中, JVM发现TestAppet是从超类java.applet.Applet继承的。所以JVM再次调用ACL来装载 java.applet.Applet类。ACL又再次按上面的顺序装载Applet类, 结果ACL发现他的父装载器已经装载了这个类, 所以ACL就直接将这个已经装载的类返回给了JVM , 完成了Applet类的装载。接下来,Applet类的超类也一样处理。最后, TestApplet及所有有关的类都装载到了JVM中。
当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。其中有个loadClass(String name, boolean resolve)方法,该方法为ClassLoader的入口点,在jdk1.2以后,loadClass方法将缺省调用findClass方法,详细内容可以参考API文档,我们编写的ClassLoader主要就是为了覆盖以上两个方法。
Java EE
Tomcat Server处理一个http请求的过程
假设来自客户的请求为:
http://localhost:8080/wsota/wsota_index.jsp
1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
3) Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5) localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
7) path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10)Context把执行完了之后的HttpServletResponse对象返回给Host
11)Host把HttpServletResponse对象返回给Engine
12)Engine把HttpServletResponse对象返回给Connector
13)Connector把HttpServletResponse对象返回给客户browser
JDK新特性
注释(Annotation),得先提一提什么是元数据(metadata)。所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。而J2SE5.0中提供的注释就是java源代码的元数据,也就是说注释是描述java源代码的。
多线程 线程
实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。优先采用实现Runnable接口的方法。首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的 static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。使用Runnable还有一个好处就是多线程应用对象可以继承别的对象而不是必须继承Thread类, 从而提高多线程对象的灵活性.
多线程的执行过程是当一个程序(一个线程)执行的过程中, 通过调用Thread.start(), 让当前的程序(线程)继续执行的同时, 那个start的Thread会同时执行位于run()方法中的代码, 多段可执行代码交替执行的过程.
由于多个线程拥有度大力的执行对战和程序执行上下文, 因此定义在线程方法中的局部变量不会出现资源共享的问题, 资源共享同步主要发生在成员变量上.
按照线程体在计算机系统内存中的状态不同,可以将线程分为创建、就绪、运行、睡眠、挂起和死亡等类型。这些线程状态类型下线程的特征为:
创建状态:当利用new关键字创建线程对象实例后,它仅仅作为一个对象实例存在,JVM没有为其分配CPU时间片等线程运行资源;
就绪状态:在处于创建状态的线程中调用start方法将线程的状态转换为就绪状态。这时,线程已经得到除CPU时间之外的其它系统资源,只等JVM的线程调度器按照线程的优先级对该线程进行调度,从而使该线程拥有能够获得CPU时间片的机会。
睡眠状态:在线程运行过程中可以调用sleep方法并在方法参数中指定线程的睡眠时间将线程状态转换为睡眠状态。这时,该线程在不释放占用资源的情况下停止运行指定的睡眠时间。时间到达后,线程重新由JVM线程调度器进行调度和管理。
挂起状态:可以通过调用suspend方法将线程的状态转换为挂起状态。这时,线程将释放占用的所有资源,由JVM调度转入临时存储空间,直至应用程序调用resume方法恢复线程运行。
死亡状态:当线程体运行结束或者调用线程对象的stop方法后线程将终止运行,由JVM收回线程占用的资源。
在Java中比较特殊的线程是被称为守护(Daemon)线程的低级别线程。这个线程具有最低的优先级,用于为系统中的其它对象和线程提供服务。将一个用户线程设置为守护线程的方式是在线程对象创建之前调用线程对象的setDaemon方法。典型的守护线程例子是JVM中的系统资源自动回收线程,它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。
jvm固定了线程和内存之间的关系, jvm的内存又分为主内存和工作内存, 线程要操作的数据放在工作内存中, 工作内存的变脸是主内存的拷贝, 线程执行完后工作内存中的变量还需要更新主内存中对应的变量.对于使用了synchornized保护的代码对主内存变量将被锁定从而保证主内存和工作内存之间的变量报纸一致性.但是使用synchonrized的代码在性能上会带来不小的损失
ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。它的内部其实可以理解为仅有一个Entry的Map, key是当前的thread, 而value则是要保存的变量.因此它只有两个方法set()将变量跟thread关联, get()方法从map中取出变量, 还有一个就是initValue方法, 是用来生成自己的ThreadLocal的时候用的, 用来给出默认值, 在get和set方法中调用)
基本类型不是new出来的则是放在栈里面,对象的引用也是放在栈里面的,只要是用new()来新建对象的,都会在堆中创建
String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
关于String str = "abc"的内部工作。Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在栈中查找有没有存放值为"abc"的地址,如果没有,则开辟一个存放字面值为"abc"的地址,接着创建一个新的String类的对象 o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。
值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!
java内存泄露的两个条件:无用,无法回收。
BigInteger能表示任意精度的整数, BigDecimal能表示任意精度的浮点数, 但都是用精度换速度的做法
容器集合
List的子类里面LinkedList和ArrayList是非同步的,而Vector和Stack是同步的, LinkedList底层采用的是双向链表(前指针+数据+后指针), 因此查询效率低, 增删效率高; ArrayList底层采用的是Array,因此查询效率高, 增删效率低; Vecotr是重量级的List, 一般在并发保证线程安全时采用
如果想跟踪添加给HashSet的元素的顺序,LinkedHashSet实现会有帮助。LinkedHashSet的迭代器按照元素的插入顺序来访问各个元素。
List中的元素有顺序, 可重复, Set中的元素无序, 不可重复(SortedSet是有序的)
Iterator的next方法将跳到下一个元素, 并返回刚刚跳过的元素, 因此使用remove方法的时候,必须先调用next方法
在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。
LinkedHashMap扩展HashMap,以插入顺序将关键字/值对添加进链接哈希映像中。
Hashtable 类似于 HashMap,但是不允许 null 键和 null 值。它也比 HashMap 慢,因为它是同步的。
效率
在方法内部频繁存取变量的时候, 使用局部变量比使用实例变量和静态变量要有更高的效率
异常对性能不利。抛出异常首先要创建一个新的对象。Throwable接口的构造函数调用名为fillInStackTrace()的本地(Native)方法,fillInStackTrace()方法检查堆栈,收集调用跟踪信息。只要有异常被抛出,VM就必须调整调用堆栈,因为在处理过程中创建了一个新的对象。
I/O
任何有能力产生数据流(源)的java io对象就可以看作是一个InputStream对象, 何有能力接收数据源(流)的java io对象我们就可以看作是一个OutputStream对象
io数据流有两种类别,一种就是InputStream/OutputStream,一种是Reader/Writer, 分别用来处理字节流和字符流, 字符也是一种字节, 为什么还要用Reader/Writer呢, 这是因为在处理字符的时候可能涉及到转码,转码主要是Reader与InputStream,以及Writer与OutputStream之间, 转码的过程都是通过InputStreamReader和OutputStreamWriter来做的, 有时候我们可能没有显式的调用这两个类, 但是相关的类在内部是做了这种转换的, 比如FileReader其实就是通过InputStreamReader将数据从FileInputStream取过来的, 比如将操作系统的文字编码转化为Unicode(因为在Java内部都是采用Unicode来保存数据的), 记住这里有一个前提,那就是操作系统当前的编码格式和文档的编码格式是一直的,如果不一致就必须指定当前的InputStream的编码格式.如果不知道字符所采用何种编码方式, 那么就不要使用Reader和Writer而应该改用InputStream和OutStream
对输入/输出流进行缓冲可以提高代码执行效率, 也就是使用BufferedXxxx和BufferedXxxx对原有的流进行封装, 缓冲是一个非常重要而基本的加速I/O访问的技术
final关键字修饰的变量,表明该变量是不变的, 但是这里的不变只是所引用本身不变, 至于引用的对象是否改变则没有约束, 比如final StringBuffer a=new StringBuffer("immutable");a.append(" broken!"); //编译通过, 这里我们可以看出, final只对引用的"值"(也就是它所指向的那个对象的内存地址)有效, 它迫使引用只能指向初始指向的那个对象, 改变它的指向会导致编译器错误, 至于它所指向的对象的变化, final是不负责的.
当你要clone的类里面含有可修改的引用字段的时候,那么你一定要把整个类的蓝图进行复制,如果对你clone得到的对象进行修改的时候还会影响到原来的实例,那么这是不可取的。所以应该这样clone()
JVM
一般来说,我们使用虚拟机的类装载时需要继承抽象类java.lang.ClassLoader,其中必须实现的方法是loadClass(),对于这个方法需要实现如下操作:(1) 确认类的名称;(2) 检查请求要装载的类是否已经被装载;(3) 检查请求加载的类是否是系统类;(4) 尝试从类装载器的存储区获取所请求的类;(5) 在虚拟机中定义所请求的类;(6) 解析所请求的类;(7) 返回所请求的类。
Java中的类的装载过程也就是代理装载的过程。比如:Web浏览器中的JVM需要装载一个小应用程序TestApplet。JVM调用小应用程序装载器ACL(Applet ClassLoader)来完成装载。ACL首先请求它的父装载器, 即系统装载器装载TestApplet是否装载了这个类, 由于TestApplet不在系统装载器的装载路径中, 所以系统装载器没有找到这个类, 也就没有装载成功。接着ACL自己装载TestApplet。ACL通过网络成功地找到了TestApplet.class 文件并将它导入到了JVM中。在装载过程中, JVM发现TestAppet是从超类java.applet.Applet继承的。所以JVM再次调用ACL来装载 java.applet.Applet类。ACL又再次按上面的顺序装载Applet类, 结果ACL发现他的父装载器已经装载了这个类, 所以ACL就直接将这个已经装载的类返回给了JVM , 完成了Applet类的装载。接下来,Applet类的超类也一样处理。最后, TestApplet及所有有关的类都装载到了JVM中。
当 JVM 需要使用类时,它根据名称向 ClassLoader 请求这个类,然后 ClassLoader 试图返回一个表示这个类的 Class 对象。通过覆盖对应于这个过程不同阶段的方法,可以创建定制的 ClassLoader。其中有个loadClass(String name, boolean resolve)方法,该方法为ClassLoader的入口点,在jdk1.2以后,loadClass方法将缺省调用findClass方法,详细内容可以参考API文档,我们编写的ClassLoader主要就是为了覆盖以上两个方法。
Java EE
Tomcat Server处理一个http请求的过程
假设来自客户的请求为:
http://localhost:8080/wsota/wsota_index.jsp
1) 请求被发送到本机端口8080,被在那里侦听的Coyote HTTP/1.1 Connector获得
2) Connector把该请求交给它所在的Service的Engine来处理,并等待来自Engine的回应
3) Engine获得请求localhost/wsota/wsota_index.jsp,匹配它所拥有的所有虚拟主机Host
4) Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
5) localhost Host获得请求/wsota/wsota_index.jsp,匹配它所拥有的所有Context
6) Host匹配到路径为/wsota的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
7) path="/wsota"的Context获得请求/wsota_index.jsp,在它的mapping table中寻找对应的servlet
8) Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类
9) 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
10)Context把执行完了之后的HttpServletResponse对象返回给Host
11)Host把HttpServletResponse对象返回给Engine
12)Engine把HttpServletResponse对象返回给Connector
13)Connector把HttpServletResponse对象返回给客户browser
JDK新特性
注释(Annotation),得先提一提什么是元数据(metadata)。所谓元数据就是数据的数据。也就是说,元数据是描述数据的。就象数据表中的字段一样,每个字段描述了这个字段下的数据的含义。而J2SE5.0中提供的注释就是java源代码的元数据,也就是说注释是描述java源代码的。
多线程 线程
实现线程,有两种方法,一种是继承Thread类,一种是实现Runnable接口。优先采用实现Runnable接口的方法。首先,把需要共享的数据放在一个实现Runnable接口的类里面,然后,把这个类的实例传给多个Thread的构造方法。这样,新创建的多个Thread,都共同拥有一个Runnable实例,共享同一份数据。如果采用继承Thread类的方法,就只好使用static静态成员了。如果共享的数据比较多,就需要大量的 static静态成员,令程序数据结构混乱,难以扩展。这种情况应该尽量避免。使用Runnable还有一个好处就是多线程应用对象可以继承别的对象而不是必须继承Thread类, 从而提高多线程对象的灵活性.
多线程的执行过程是当一个程序(一个线程)执行的过程中, 通过调用Thread.start(), 让当前的程序(线程)继续执行的同时, 那个start的Thread会同时执行位于run()方法中的代码, 多段可执行代码交替执行的过程.
由于多个线程拥有度大力的执行对战和程序执行上下文, 因此定义在线程方法中的局部变量不会出现资源共享的问题, 资源共享同步主要发生在成员变量上.
按照线程体在计算机系统内存中的状态不同,可以将线程分为创建、就绪、运行、睡眠、挂起和死亡等类型。这些线程状态类型下线程的特征为:
创建状态:当利用new关键字创建线程对象实例后,它仅仅作为一个对象实例存在,JVM没有为其分配CPU时间片等线程运行资源;
就绪状态:在处于创建状态的线程中调用start方法将线程的状态转换为就绪状态。这时,线程已经得到除CPU时间之外的其它系统资源,只等JVM的线程调度器按照线程的优先级对该线程进行调度,从而使该线程拥有能够获得CPU时间片的机会。
睡眠状态:在线程运行过程中可以调用sleep方法并在方法参数中指定线程的睡眠时间将线程状态转换为睡眠状态。这时,该线程在不释放占用资源的情况下停止运行指定的睡眠时间。时间到达后,线程重新由JVM线程调度器进行调度和管理。
挂起状态:可以通过调用suspend方法将线程的状态转换为挂起状态。这时,线程将释放占用的所有资源,由JVM调度转入临时存储空间,直至应用程序调用resume方法恢复线程运行。
死亡状态:当线程体运行结束或者调用线程对象的stop方法后线程将终止运行,由JVM收回线程占用的资源。
在Java中比较特殊的线程是被称为守护(Daemon)线程的低级别线程。这个线程具有最低的优先级,用于为系统中的其它对象和线程提供服务。将一个用户线程设置为守护线程的方式是在线程对象创建之前调用线程对象的setDaemon方法。典型的守护线程例子是JVM中的系统资源自动回收线程,它始终在低级别的状态中运行,用于实时监控和管理系统中的可回收资源。
jvm固定了线程和内存之间的关系, jvm的内存又分为主内存和工作内存, 线程要操作的数据放在工作内存中, 工作内存的变脸是主内存的拷贝, 线程执行完后工作内存中的变量还需要更新主内存中对应的变量.对于使用了synchornized保护的代码对主内存变量将被锁定从而保证主内存和工作内存之间的变量报纸一致性.但是使用synchonrized的代码在性能上会带来不小的损失
ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。它的内部其实可以理解为仅有一个Entry的Map, key是当前的thread, 而value则是要保存的变量.因此它只有两个方法set()将变量跟thread关联, get()方法从map中取出变量, 还有一个就是initValue方法, 是用来生成自己的ThreadLocal的时候用的, 用来给出默认值, 在get和set方法中调用)
发表评论
-
【转帖】解码OutOfMemoryError:PermGen Space
2013-12-30 11:22 1065本文由 ImportNew - Peter Pan ... -
JBoss下面部署应用的Log4j日志不能显示问题
2012-08-31 13:36 5496在应用的WEB-INF目录下面增加该文件:jboss-depl ... -
WEB容器启动的时候,加载常用数据到内存
2010-08-07 10:41 5693项目中,有很多数据是基本上不变的,同时用到的频率还比较高,如果 ... -
java.lang.OutOfMemoryError: PermGen space的解决办法
2010-05-31 15:38 1703修改tomcat 的catalina.bat文件,加入: se ... -
使用UrlRewriteFilter动态URL静态化
2010-04-20 15:42 1594先看两种URL的写法: 引用http://www.xxx.co ... -
Eclipse里maven的project报Unbound classpath variable: 'M2_REPO/**/***/***.jar
2010-04-19 16:49 11074Eclipse里maven的project报Unbound c ... -
java序列化(Serializable)的作用和反序列化
2010-03-24 11:03 5401这里转载一篇讲解java序 ... -
java.util.Collections.sort对List进行排序
2010-03-23 16:41 2005List<userDO> list = new A ... -
【转贴】Tomcat解析之简单web服务器
2010-02-11 10:46 1285gogole_09 写道 之前有java ... -
iText生成PDF文件,每页显示页码以及总页数的实现
2009-11-10 16:35 18121如果想在页眉或者页脚加上第x页这样的信息,用普通的Header ... -
iText导出PDF使用小结
2009-11-10 15:42 4207新建一PDF页面,设置输出流: Document docume ... -
jar包里面的代码如何读取jar包中的配置文件?
2009-10-09 16:28 4658先看代码目录结构: src/weather/ Quer ... -
JAVA登陆MSN并且获取联系人列表
2009-09-22 14:15 2824package msn; import net.sf. ... -
实战篇:设计自己的Annotation
2009-08-26 16:33 1289【转载】From:http://lighter.iteye.c ... -
支付宝外部商家接口中的return_url和notify_url
2009-08-25 15:34 5197return_url: 1、同步返回接口,作为参数传递给支付宝 ... -
多JBOSS公存时需要修改的端口号
2009-07-13 13:56 18771.修改server/default/conf/jboss_s ... -
struts.properties配置
2009-07-07 11:04 1245struts.properties文件在WEB-INF/cla ... -
request.getHeader("REFERER")获取来访页面地址
2009-07-01 10:46 4580request.getHeader("REFERER ... -
split分隔特殊字符"| ^ . *"等特殊字符
2009-06-18 16:16 4138String a = "china|hangzhou ... -
如何让tomcat支持软链接
2009-06-15 20:56 3502最近在做个图片上传的页面,需要把上传的图片放到tomcat部署 ...
相关推荐
Java最详细的帮你复习面试指南 回顾所有的Java知识 +笔记 +面试指南+简历帮助 全都是干货
适合面试者复习,更适合初学者总结经验用.里面有三份.
408复试面试题 计算机网络和计算机操作系统的个人学习笔记,涵盖日常期末复习及计算机408考研知识点,以及Java面试重点
计算机网络和计算机操作系统的个人学习笔记,涵盖日常期末复习及计算机408考研知识点,以及Java面试重点
《Java基础复习笔记.docx》是一份宝贵的学习资源,旨在帮助那些已经具有一定Java编程基础的学习者巩固知识、进行复习以及更深入地理解Java编程的核心概念。以下是对这个资源的详细描述: 全面的复习内容:这份资源...
Java 面试题(按照学习过程复习).zip
18天java学习之经典笔记,适合复习、考试、面试之用
这一份文档由华为架构师编写,梳理了Java所有高难度知识点:JVM,多线程, IO, Java与系统底层的交互详情等等,适合面试BAT等大厂之前做为复习资料 Java 架构面试知识点梳理.
学习java后,为准备面试进行的系统复习笔记,自我感觉很是全面,纯手打,补充过很多面试遇到的坑。如果你还为面试发愁,不知所措,相信我,这个不会让你后悔。愿每一个人都被生活温柔以待
这是开始复习的第一天,希望能够坚持,每天复习,提升自己的能力,欢迎小白一起学习,一起进步,这是复习的第一篇笔记,希望能够对你产生帮助
内容概要 韩顺平版Java基础笔记是一套详尽的Java入门教程,内容包括: Java语言概述和环境搭建 基本数据类型、变量和运算符 控制语句:条件语句和循环...面试准备:为求职者提供Java基础知识点的复习,增强面试信心。
前人学习笔记加自已的学习笔记整理而来,是面试前复习java的好资料,对初学者尤其有用.
内容概要 ...面试准备:为求职过程中的Java框架相关问题提供复习资料。 知识更新:帮助在职开发者了解和学习最新的框架特性和改进。 其他说明 实战案例:通过实际的应用案例,展示框架的具体使用和配置
Linux课程学习笔记 -韩顺平 包含c/c++/python/java 专项 面试题 PDF PPT 笔记 面试题 (百度网盘链接 永久有效) 自学,做笔记,复习可用
内容概要 Java领域基础部分aS笔记涵盖了Java编程语言的核心概念,包括但不限于: Java数据类型和变量 控制流程语句(if-else, switch, for, while等) ...面试准备:为即将参加技术面试的候选人提供复习资料。
《Java基础课程全套笔记.doc》是一份珍贵的学习资源,专为那些希望深入研究和掌握Java编程高级概念的学习者和开发者而创建。以下是对这个资源的详细描述: 全面的高级主题覆盖:这份文档涵盖了Java编程的高级主题,...
一线互联网大厂大数据面试题库,大数据全栈学习【生态组件,技术栈,数据流,数据仓库,数据库,指标体系,血缘关系,元数据管理,数据质量,DataWorks,Hadoop,Spark,Flink,面试,笔记文档,实战练习、采集、存储...
计算机科学学习笔记:高级mysql、高级redis、分布式、集群、架构、云…… :dragon: Java程序员的必备Linux运维技能,包括各种服务器软件的安装和运维等基本运维参考文档。 说明 本文档基于创建,部署在GitHub Page...
学习笔记:由资深学者精心整理的学习笔记,重点突出,为您梳理课程脉络,把握核心内容。 复习资料与试卷:涵盖了各类复习资料和历年试卷,助您备战考试,查漏补缺,提高应试能力。 作业答案:提供完整的作业答案及...