欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  资讯频道

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

程序员文章站 2022-04-20 11:42:31
...
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. 使用双重锁判定可以大幅降低锁的征用。比如:
class ObjInstance {
        //单例
    private static ObjInstance oi = new ObjInstance();
 
    private static User user;
 
    private ObjInstance() {
    }
 
    public static User getUserInstance() {
 
        if (user == null) {// 无锁判定
            synchronized (oi) {
                if (user == null) {// 加锁判定
                    user = new User(1, "zs");
                }
            }
        }
 
        return user;
    }
 
}

13. 进程与线程的关系:

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