- 浏览: 603155 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
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 1101本文由 ImportNew - Peter Pan ... -
JBoss下面部署应用的Log4j日志不能显示问题
2012-08-31 13:36 5536在应用的WEB-INF目录下面增加该文件:jboss-depl ... -
WEB容器启动的时候,加载常用数据到内存
2010-08-07 10:41 5715项目中,有很多数据是基本上不变的,同时用到的频率还比较高,如果 ... -
java.lang.OutOfMemoryError: PermGen space的解决办法
2010-05-31 15:38 1734修改tomcat 的catalina.bat文件,加入: se ... -
使用UrlRewriteFilter动态URL静态化
2010-04-20 15:42 1625先看两种URL的写法: 引用http://www.xxx.co ... -
Eclipse里maven的project报Unbound classpath variable: 'M2_REPO/**/***/***.jar
2010-04-19 16:49 11106Eclipse里maven的project报Unbound c ... -
java序列化(Serializable)的作用和反序列化
2010-03-24 11:03 5427这里转载一篇讲解java序 ... -
java.util.Collections.sort对List进行排序
2010-03-23 16:41 2040List<userDO> list = new A ... -
【转贴】Tomcat解析之简单web服务器
2010-02-11 10:46 1314gogole_09 写道 之前有java ... -
iText生成PDF文件,每页显示页码以及总页数的实现
2009-11-10 16:35 18305如果想在页眉或者页脚加上第x页这样的信息,用普通的Header ... -
iText导出PDF使用小结
2009-11-10 15:42 4236新建一PDF页面,设置输出流: Document docume ... -
jar包里面的代码如何读取jar包中的配置文件?
2009-10-09 16:28 4680先看代码目录结构: src/weather/ Quer ... -
JAVA登陆MSN并且获取联系人列表
2009-09-22 14:15 2850package msn; import net.sf. ... -
实战篇:设计自己的Annotation
2009-08-26 16:33 1337【转载】From:http://lighter.iteye.c ... -
支付宝外部商家接口中的return_url和notify_url
2009-08-25 15:34 5252return_url: 1、同步返回接口,作为参数传递给支付宝 ... -
多JBOSS公存时需要修改的端口号
2009-07-13 13:56 19411.修改server/default/conf/jboss_s ... -
struts.properties配置
2009-07-07 11:04 1270struts.properties文件在WEB-INF/cla ... -
request.getHeader("REFERER")获取来访页面地址
2009-07-01 10:46 4610request.getHeader("REFERER ... -
split分隔特殊字符"| ^ . *"等特殊字符
2009-06-18 16:16 4170String a = "china|hangzhou ... -
如何让tomcat支持软链接
2009-06-15 20:56 3542最近在做个图片上传的页面,需要把上传的图片放到tomcat部署 ...
相关推荐
在这个阶段的学习中,尚硅谷提供了2023年的学习笔记和面试题,帮助你提升Java技能并为求职做好准备。 首先,多线程是Java的一个关键特性,允许程序同时执行多个任务。理解线程的创建(通过Thread类或实现Runnable...
这份“笔记_JAVA基础篇,面试必问的那些事”压缩包文件,显然是为准备Java面试的人提供了一份详尽的复习资料。以下是Java基础知识的一些关键点,这些都是在面试中经常被问到的话题: 1. **Java语法基础**:Java的...
Java是世界上最流行的编程...这个"java面试宝典与相关学习笔记"将帮助你系统地复习这些关键知识点,通过实例解析和常见面试问题,提升你的面试表现,助你在Java程序员的求职道路上一臂之力。祝你学习进步,面试顺利!
这份"java面试,基础学习笔记"包含了针对面试者复习和初学者学习的关键知识点,旨在帮助你深入理解和掌握Java的核心概念。 在"core_java"部分的学习笔记中,你将深入探讨Java的基础语法和核心特性。这包括但不限于:...
Java最详细的帮你复习面试指南 回顾所有的Java知识 +笔记 +面试指南+简历帮助 全都是干货
这份"Javaq备战秋招面试题-重点学习笔记.zip"文件包含了面试必备的Java知识点,帮助你全面复习并提升技能。 1. **基础语法**:理解并掌握Java的基础语法是所有Java程序员的起点,包括变量、数据类型(基本类型和...
Java学习笔记之大鹏JAVA终级总结,是针对Java编程语言深入学习和面试准备的一份综合资料。这份总结涵盖了从基础知识到高级概念的多个方面,旨在帮助初学者理解和掌握Java的核心概念,同时解决面试中可能出现的关键...
这份“Java面试笔记整理”旨在帮助求职者系统性地复习和掌握Java面试的关键知识点。 首先,Java基础是面试的基石。这包括对Java语法的理解,如变量、数据类型、运算符、流程控制语句(如if-else、switch-case、for...
【Java面试大全】是针对Java开发者的一份全面的面试准备指南,主要涵盖了Java SE的基础知识、面向对象特性、语法细节以及一些高级...通过系统学习和复习这些知识点,面试者能够更好地应对各种Java相关职位的面试挑战。
408复试面试题 计算机网络和计算机操作系统的个人学习笔记,涵盖日常期末复习及计算机408考研知识点,以及Java面试重点
计算机网络和计算机操作系统的个人学习笔记,涵盖日常期末复习及计算机408考研知识点,以及Java面试重点
文档中还提到,内容是作者个人学习笔记的整理,其中也包含了一些书籍推荐,供读者进一步深入学习。此外,文中还提到了自动化上传方案,说明了作者在内容整理和分享方面也做了很多工作。这本复习资料强调原创性,鼓励...
这份资源旨在帮助Java开发者系统地复习和掌握核心概念,以便在面试中展现出扎实的技术功底。学习笔记则提供了个人在学习过程中整理的要点、理解和实践经验,是宝贵的自学资料。 一、Java基础知识 这部分通常包括...
这个压缩包的学习资料可能包括PDF文档、笔记、代码示例等形式,帮助你系统复习和巩固这些知识点。通过深入学习并实践这些内容,你将能够更好地应对Java开发的面试挑战,提高你的专业技能,为你的职业生涯铺平道路。...
Java学习笔记是一个全面掌握...总之,这份Java学习笔记是提升编程技能的宝贵资源,无论你是准备面试,还是想要深入技术细节,都能从中受益匪浅。通过系统的脑图学习,你将能够更有效地理解和应用这些关键的技术知识。
《Java面试问题集.pdf》很可能是包含上述知识点的具体题目集,通过这份资料,你可以系统地复习和巩固Java技术体系,为面试做好充分准备。在准备过程中,不仅要理解答案,还要思考为什么会有这样的设计,以及如何将所...
学习java后,为准备面试进行的系统复习笔记,自我感觉很是全面,纯手打,补充过很多面试遇到的坑。如果你还为面试发愁,不知所措,相信我,这个不会让你后悔。愿每一个人都被生活温柔以待
这个压缩包包含两部分内容:笔记.docx 和 PPT.pptx,可能分别对应着课程的学习笔记和讲解幻灯片。 【描述】链接指向的是CSDN(China Software Developer Network)的一个资源上传页面,虽然具体内容无法直接在这一...
"程序员面试学习笔记以及相关经验记录"这个资料集合,无疑为准备面试的程序员提供了一份宝贵的参考资料。这份名为"noteTest-master"的压缩包文件很可能包含了面试准备的各种要素,包括但不限于常见面试题、解题思路...