Java 学习

学校的Java课真的是一点用都没有,教的都是皮毛,还得自己看。

参考书目:
深入理解java虚拟机
实战Java高并发程序设计

本是学习记录贴,若有幸被人发现,需要了解,还是直接看参考书目吧,就不让别人走我老路了,对于学习而言,看书比看博客不知道高到哪儿去。

JVM

Java是多平台的语言,得益于JVM,任何机器只要有这一层环境,就可以运行Java程序,但缺点是不能像c语言那样直接操作底层,需要一些手段,比如native方法。

运行时数据

程序计数器:

存储了当前运行代码的字节码的地址 若执行native方法,则为空。

java虚拟栈:

对应线程的局部变量(基本数据类型,对象引用,returnaddress没有对应的java类型)

本地方法栈:

存放native方法。

Java堆:

最大的一块空间,存放几乎所有对象的实例。(内存回收的大头,新生代,老生代)

方法区:

存放静态变量,常量,已被虚拟机加载的类信息,被编译器编译后的代码等。(垃圾回收,永久代,不过,不是所有JVM都有这个)

运行常量区:

存放各种字面符号和常量。

new一个对象

类加载

在常量池中定位到一个符号引用,检查是否类加载了

内存分配

内存规整:指针分配
内存有碎片:空闲列表

内存分配的同步
1.加锁
2.对不同的线程分配不同的空间
thread local allocation buffer
但对分配 本地线程分配缓存 需要同步锁定

对所有的内容空间全设为0

设置对象头

构造函数

定位一个实例对象

reference 数据类型
句柄访问:句柄池,(实例池)对象的实例数据,对象的类型
直接访问:对象实例数据,对象类型

OutOfMemoryError

垃圾回收机制

引用计数

对每个实例对象都添加一个计数值,每这个对象被引用过一次,计数值就加一,当引用失效,就减一。
缺点:循环引用

可达性分析

多棵树:以GC roots为根,以引用链为边。其他就是要回收的对象。
GC roots:
Java虚拟栈:引用对象
方法区:静态属性,常量
本地方法栈:native方法

四种引用

强软弱虚
强:直到

缓刑

可达分析是要回收,但还有机会:只要finalize()方法使用过或者没有覆盖finalize()方法,那就可以不回收,逃过一劫。

垃圾回收算法

标记清除
先标记,然后清除。
1.会产生碎片
2.效率低

复制算法
滚动的思想,dp滚动数组
浪费空间
新生代回收的普遍实现,
80%Eden,10%survivor

标记整理
标记,按顺序整理

多种收集器
serial :单线程,stop the world
parnew :多线程版serial,依旧stop the world
parallel scavenger:多线程,但是关注吞吐量 用户代码时间/总时间
serial old:运行在老年代
parnew old:运行在老年代
cms:
基于标记清除
初始标记(占)-》并发标记-》重新标记(占)-》并发清除
标记清除所以碎片,所以需要一定时间进行整理,并且老年代没怎么满就要full gc

g1:
并行与并发
分代收集
空间整合:整体标记-整理,局部复制
可预测的停顿

如何实现可预测?
化整为零:把java堆分成若干个Region,串成一个优先列表,根据可允许的时间释放价值最大的空间
问题:堆之间的引用关-->remember set

初始标记-》并发标记-》最终标记-》筛选回收

新生代和老年代内存分配问题

先放eden
大对象放在老年代
长期存活的对象放在老年代
新-》老:
1.MAXTenuringThreshold
2.survivor 空间相同年龄所有对象的大小大于Survivor空间的一半,大于这个年龄的对象晋升老年代

多线程

线程和进程的区别
线程是轻量的进程;

进程拥有独立的地址空间,同一进程内的线程共享本进程的地址空间。
进程拥有独立的资源,同一进程内的线程共享资源。

线程的状态

new running waiting timed-waiting blocked terminated
图:额,手画吧

生成线程

在java中,要使用或者说new(生成)一个线程。
继承runnable接口或者Thread类。

终止线程

stop:不好,会强制结束进程,导致不合法的解锁,会导致数据不一致

线程中断:就是通知线程有人让你中断,至于中断该做什么,要自己重新编写中断处理逻辑

wait和notify

这两个方法在调用之前,必须获得该对象的监视器。
notify:公平锁,随机挑选的

join,yeild

join:我来断后
yeild:我把要做的做好了,我也不继续占着茅坑不拉屎,虽然我还有一些善后工作,但大家还是一起竞争吧。

volatile

有序性
可见性
无原子性

synchronized

对象
实例方法
静态方法

重入锁 Reentrantlock

手动加锁,释放锁。对于一个线程,它可以重复的多次多次加锁。
lock():获得锁
lockInterruptibly():获得锁,但优先响应中断
tryLock():尝试获得锁,要是成功true,否则false
tryLock(time,unit):给定时间内尝试获得锁
unlock():释放锁

原子状态:CAS
等待队列:没有请求到锁的线程
阻塞原语:pack,unpack

信号量

锁的扩展,同一资源

线程复用:线程池

目的:避免频繁地创建和销毁线程,达到线程的复用

五种线程池:
newfixedThreadPool():
newSingleThreadPool():
newcacheThreadPool():
newSingleThreadScheduledExecutor():
newScheduledThreadPool():

七个参数:
ThreadFactory:线程工厂
corePoolSize: 指定线程池中线程的数量
maxinumPoolSize:最大线程数量
Keepalivetime:存活时间
unit:时间单位
workqueue:被提交但未执行的任务 blockqueue接口对象,仅能放runnable对象
Handler:拒绝策略

workqueue有点东西
SynchronousQueue:保存,直接提交,超过MaxinumPoolSize,执行拒绝策略。
arraryBlockingqueue:有界的任务队列
linkedBlockingqueue:无界的任务队列
PriorityBlockingqueue:优先任务队列

各个线程池的参数情况:
newfixedThreadPool: corePoolSize=maxinumPoolSize,+ LinkedBlockingQueue;
newSingleThreadPool: 与fixed差不多,置为1
newcacheThreadPool: corePoolSize=0,maxinumPoolSize无穷大,直接提交Synchronous

Collection类及并发类

只列举常用的集合类及其父接口

数组 继承list接口

arraylist:默认大小10 负载因子 0.75 ×1.5
linkedlist:
vector(stack):默认大小为10 负载因子0.75 ×2

集合

TreeSet
HashSet:默认大小为16,负载因子 ×2
LinkedHashSet: 和Hashset一样

映射

TreeMap
HashMap:默认大小为16,负载因子 0.75 ×2
HashTable:默认大小为11,负载因子 0.75 ×2+1

Legacy:vector,stack,Hashtable 都是线程安全的,但是效率堪忧。

常问问题:
1、HashTable和HashMap的异同
1.hashtable是线程安全的,使用了synchronize 关键字,粗暴,效率差;hashMap线程不安全,需要Collections.synchronizedMap方法来包装hashmap
2.Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。
3.Map没有contains,只有containsValue和containsKey ,contains==containsValue
4.hashtable key值和value值不能都是null
5.hashtable直接 pos为key的hash值%len,hashmap两次计算hash值,为

2、ConcorrentHashMap
1.jdk1.7 采用了减小锁粒度,将数组空间分成16份,分别加锁。
2.jdk1.8 锁定节点,粒度更小,采用hash+红黑树的组合

设计模式

单例设计模式

饿汉式

public class A{
    private static A instance = new A();
    private A(){

    }
    public static A getinstance(){
        return this.instance;
    }
}; 

懒汉式 线程不安全

public class A{
    private static A instance ;
    private A(){

    }
    public static A getinstance(){
        if(this.instance==null) this.instance = new A();
        return this.instance;
    }
}; 

懒汉式 线程安全
只有第一次需要加锁

public class A{
    private static volatile A instance;
    private A(){

    }
    public static A getinstance(){
        if(this.instance==null){
            sychronized(A.class){
                if(this.instance==null) 
                    instance = new A();
            }
        }
        return this.instance;
    }
};

枚举式

public enum A{
    instance;
}
添加新评论