Java知识库,程序员必须Mark!

1. 若JVM进程中,只剩下后台线程,则该进程就结束了。可以使用setDaemon(true)将线程设置为后台线程。

2. 使用线程的join()方法,可以等待多个线程子任务执行完成后,进行合并结果的操作;但是join只是对线程单纯的顺序join,但是这个顺序不一定是 线程真正结束的顺序,而CompletionService可以按照线程结束后的顺序给我们返回结果。另外,一个更大的区别在于线程的Join操作是针对 线程的合并操作,这就意味着为每个任务创建对应的线程,如果任务数很多将导致创建大量的线程来处理,而CompletionService是基于线程池的 任务,无论任务数量多少,线程的数量是可以控制的。

3. 线程是基于栈的,可以使用getStackTrace()方法,查看当前线程的栈轨迹。

4. 栈空间是每个线程私有的空间,当调用某方法时将给该私有栈分配空间,在方法内部再调用方法还会继续使用相应的栈空间,方法返回时收回相应的栈空间(不论是否抛出异常)。这块空间通常也叫做“工作内存”,堆空间也叫做“主内存”。

5. 普通变量的修改并不一定立即写回到主存,而线程读取时也不需要每一次都从主存中读取;

6. 使用volatile修饰变量,可以保证多线程中的共享变量始终是可见的(但这并不保证volatile引用对象内部的属性是完全可见的);

volatile还有一个作用就是防止相关性代码的重排序,从指令级别达到了轻量级锁的目的。

7. 线程池初始化时是没有任何线程的,有任务是才会创建线程;而数据库连接池初始化时,是已经存有一定的连接了,否则用到时再创建会耗时的。

8. JDK动态代理在生成动态字节码时,并不是通过实现类创建子类的方式,而是通过类所拥有的接口列表来完成的。也就是说,生成的类和实际的类一点关系都没 有,而是一个独立的类,只是方法名和接口的方法名完全一样。但是生成的代理对象初始化时,会传递一个handler参数,而这个handler里是包含实 际实现类(target)的,所以代理类调用方法时,实际上是使用target调用方法的。

顺便说一下,Cglib动态代理是继承实际类生成子类,调用方法时也不是使用反射(反射效率相对较低),而是使用FastClass通过索引调用相应的方法的。

9. spring配置文件中component-scan配置中的base-package属性是要扫描的路径,spring会扫描相应classpath下 所有与base-package相关的路径,包括jar包的路径,但是不会遍历jar包里的类,所以如果把加载的Bean放在jar包中,那么即使是 base-package="*"也是扫描不到的。

10. 在web应用中,可以通过 ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest()获取到HttpServletRequest对象。

11. Spring将Connection对象放入了一个ThreadLocal变量中,而且是以Map的方法存在的,Map的key是DataSource。 在具有事务的方法中我们拿到的连接不是Connection本身,而是被代理的对象,所以两次获取到的Connection的HashCode是不同的。 但是代理类对象中目标对象是相同的(上面也说过),都是原始的Connection连接,所以如果在同一个事务中,那么无论多少次获取出来的连接,其内部 的target属性都是同一个。

12. 使用双重锁判定可以大幅降低锁的征用。比如:

Java代码
  1. class ObjInstance {
  2.         //单例
  3.     private static ObjInstance oi = new ObjInstance();
  4.     private static User user;
  5.     private ObjInstance() {
  6.     }
  7.     public static User getUserInstance() {
  8.         if (user == null) {// 无锁判定
  9.             synchronized (oi) {
  10.                 if (user == null) {// 加锁判定
  11.                     user = new User(1, "zs");
  12.                 }
  13.             }
  14.         }
  15.         return user;
  16.     }
  17. }

13. 进程与线程的关系:

比如有一个大工厂,里面每一个车间都是一个‘进程’,车间里的工人就是‘线程’,车间里有一个‘公共厕所’。那么,当工人上厕所时要锁上门,人少时直接就 完事了;但人多时只能在厕所门口等,等里面的人出来才能进去(锁着门呢)。当然这只是一般的情况,并没有考虑优先级等。

  1. da shang
    donate-alipay
               donate-weixin weixinpay

发表评论↓↓