day01
1.Lambada表达式:在JavaSE8中出现的新特性,用于将大量代码块简便引用
口诀:拷贝小括号 写死右箭头 落地大括号
()->{}
2.Lock锁:和Synchronized的做用一致
不一样处:Lock是在Java接口层面的一个接口,能够为多个类提供锁机制mysql
Lock lock = new ReentrantLock();算法
day02sql
多线程口诀:操做,线程,资源类数据库
ArrayList:线程不安全,扩容时须要扩1.5倍,在高并发时容易发生Java.util.ConcurrentModifictaionExcepiton。通常使用CopyOnWriteArraylist来解决并发问题
HashSet:底层原理HashMap.线程不安全,在高并发时容易发生Java.util.ConcurrentModificationException,通常使用CopyOnWriteArraySet来解决问题。
HashMap:在高并发时容易实现Java.Util.ConcurrentModificationExcaption的异常,解决方法:使用ConcurrentHashMap便可解决问题。
解决高并发的问题:
1.Vector list = new Vector();
2.List list = Collections.synchronizedList(new ArrayList());
3.CopyOnWriteArraylist list = new CopyOnWriteArraylist();数组
CopyOnWriteArraylist的原理解释:实现了读写分离,写时复制的原理
在往一个容器里添加元素的时候,不直接往当前容器的Object[]添加,而是先将该容器复制一份,当作Object[] newElements,而后往新的容器里添加东西,添加完以后,在将原容器的引用指向新的容器,从而实现对容器进行读取。这是一种读写分离的思想。。。适合读多写少的场景
在CopyOnWriteArrayList中,初始化过程当中会建立一个数组。数组的长度为0;new Object[0]
源码以下:
public boolean add(E e)
{
final ReentrantLock lock = this.lock;安全
lock.lock();数据结构
try{
Object[] ele ments = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
finally {
lock.unlock();
}
}
synchroized锁机制:
1.一个对象里面有多个synchronized方法时,当一个线程进行调用时,其余线程不能进入,只能在外面等待
synchronized锁的是当前的对象,并不是只是该方法。
2.在多线程并发里面添加一个普通的方法与synchronized的方法毫无影响。
3.全部的静态同步方法用的也是同一把锁——类对象自己,就是咱们说过的惟一模板Class,具体实例对象this和惟一模板Class,这两把锁是两个不一样的对象,因此静态同步方法与普通同步方法之间是不会有竞态条件的。可是一旦一个静态同步方法获取锁后,其余的静态同步方法都必须等待该方法释放锁后才能获取锁,
多线程的方法:判断/干活/通知 , 在多线程的互相交互中,为了使交互过程当中不出现虚假唤醒现象,则不能使用if进行判断,要使用while进行判断。
令:若是有两个线程A,B 则线程的选择非A即B ,所以在线程的互相交换中。不会有其余的线程进行干扰。而若是增长线程数,增长到4个,则四个线程的交互过程可能会出现互相争抢资源的状况发生,势必会形成线程的紊乱。所以在线程的交互过程当中,
**若是使用的是Lock加锁并不是synchronized要使用:
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
Condition的形式进行对应的等待机制和唤醒机制的体现,
condition.await();
condition.singalAll();唤醒所有
condition.singal();唤醒单个
**若是使用的是synchronized加锁,则须要使用
this.wait();
this.nitifyAll();多线程
day03并发
1.ReentrantReadWriteLock();读写锁机制
在读取与写入时,读操做容许并发操做,可是写操做并不容许并发操做,因此须要给资源类加锁.
通常会加一个lock的锁与一个解锁, 可是在运行过程当中,虽然能够精确的控制写操做的并发操做,可是同时也限制了读操做的 并发操做。这并不符合咱们的设想,因而为了给读和写分别加上不一样的锁,
咱们引入了ReentrantReadWriteLock的锁机制,他能够限制写操做的并发,可是并未限制读操做的并发操做
2.CountDownLatch:CountDownLatch是一个同步工具类,它容许一个或多个线程一直等待,直到其余线程执行完后再执行。
能够等待其余的线程执行完毕后进行执行
3.CyclicBarrier:也是一个同步工具类。他在等待全部的代码执行完毕以后再执行代码。
4.Semaphore是一种在多线程环境下使用的设施,该设施负责协调各个线程,以保证它们可以正确、合理的使用公共资源的设施,也是操做系统中用于控制进程同步互斥的量。
void acquire():今后信号量获取一个许可前线程将一直阻塞。至关于一辆车占了一个车位。jvm
void release(int n):释放n个许可。
5.得到多线程的方法:
1)实现runnable接口方法
2)继承Thread类
3)实现Callable接口(与runnable接口的方法不一样之处在于,①.Callable能够接收返回值②落地的实现方法有区别③Callable能够抛异常)
4)线程池技术
6.BlockingQueue
1)ArrayBlockingQueue: ArrayBlockQueue:一个由数组支持的有界阻塞队列。按 FIFO(先进先出)原则对元素进行排序,建立时必须明确大小。
2)该方法具备多个添加以及取出元素的方法
a)add添加方法,对应remove的移除方法。该方法若是在没有值时进取值运算的话,会报异常,碰到其余的信息也会报相关的异常
b)offer添加方法,对应poll的移除方法,该方法若是出现上述状况的话,没有值不会包异常,直接返回null,添加成功的话就显示true,失败就显示false。
c)put 添加方法,对应take移除方法, 该方法若是也有上述状况出现的话,就直接堵塞
7.ExecutorService。线程池技术
a)通常不多用其余两种的线程方法,FixedThreadPool和SinglThreadPool由于容许的建立的数量过大,会致使OOM
CacheThreadPool和ScheuledThreadPool容许的线程数量太多,会致使OOM
b)通常都采用自定义线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
int corePoolSize,//常驻的线程
int maximumPoolSize,//最大的线程数
long keepAliveTime,//除了常驻线程之外的存活时间
TimeUnit unit,//存活时间的单位
BlockingQueue<Runnable> workQueue,//阻塞队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler//拒绝策略
//将以上的参数进行设置,就是在设置池中参数的信息
);
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"办理业务");
} );
利用Lambada表达式技术,调用所须要的线程
8.为何须要使用condition来实现lock能够实现的功能
之前的方式只能一个等待队列,在实际应用时可能须要多个,好比读和写。为了这个灵活性,lock将同步互斥控制和等待队列分离开来,互斥保证在某个时刻只有一个线程访问临界区(lock本身完成),等待队列负责保存被阻塞的线程(condition完成)。
day04
1.类加载器(作的工做至关于快递员的工做,将class字节码文件加载到内存中去,并将这些内容转化为方法区中的运行时数据结构,而且ClassLoader类加载器只负责将class文件进行加载,至因而否能够运行取决于(Execution Engine执行引擎))
类加载器一共有四种分别是:
a) Bootstrap类启动类加载器(全部Java自带的类存放在rt.jar包中) :属于根加载器,即从Java诞生之日起,全部的原厂类都在这里进行加载
b) Extension扩展类加载器 :在Java发展了多年之后发现须要进行扩展,因此就诞生了扩展类加载器
c) AppClassLoader应用程序类加载器 :用户本身写的类,用该类加载器进行加载
d) 用户自定义加载器 :不多使用
2.双亲委派机制
当一个类在收到类加载请求时,他本身首先不会对类进行加载,而是调用父类的方法进行调用查询是否已经对该方法进行了调用,若是在父类中查到了就继续将该类进行加载,若是没有找到该类就继续向上调用方法查询是否已经对该方法进行了调用,在顶端父类中若是找到了,就对该类进行加载,若是找不到,子类加载器才尝试去加载
3.NativeInterface:本地接口
由于Java语言的有些部分没法借用c语言,只可以引用,因此有一个本地库,用来引用c的一些源码
4.程序计数器
每一个线程中都有一个程序计数器,程序计数器是线程私有的,他的做用是用来存储指向下一条指令的地址
5.栈
栈也叫栈内存,用于Java程序的执行。每当一个线程建立时就会生成一个栈内存,当线程毁灭时栈内存也跟着毁灭,不存在垃圾回收机制
栈内存的运用原理:每当一个方法被调用时就会产生一个栈帧,栈帧的顺序是,先入后出,后入先出。若是栈的内存被存满以后就会报出异常
Java.lang.StackOverFlowError
6.方法区是用来加载模板类的(.Class)也是共有的,并不是私有的
7.堆内存
堆内存分为三部分:年轻代,老年代,永久代
新生区(伊甸区,幸存1区,幸存2区),养老区,永久存储区
day 05
1.GC(分代收集算法)
a)频繁收集新生代
b)较少收集老年代
GC通常分为两种:
a)minorGC:主要是针对新生代的Java对象进行GC,很频繁,由于Java对象通常都出如今新生代
b)majorGC主要是针对老年代进行GC 不频繁
2.GC的四大算法:
2019-10-21 18:47:13 如何判断对象依旧存活:可达性分析算法:基本思想是经过一系列称为“GC Root”的对象(如系统类加载器、栈中的对象、
处于激活状态的线程等)做为起点,基于对象引用关系,开始向下搜索,所走过的路径称为引用链,当一个对象到
GC Root没有任何引用链相连,证实对象是不可用的。
1).引用计数法 通常不使用
2).Copying算法 因为内存的缘由 HpotJVM通常新生代分为三个部分 伊甸园区 幸存1区 幸存2 区 比例为8;1;1 在第一次GC时 ,将伊甸区存活的对象进行copy到To区,而在FROM区中,存活的对象依然根据本身的时间长短进行判断,若是达到15,就能够到养老区,若是没有到15 的话,就复制到To区进行等待,(这时全部的对象已经都在To区内了)。将To区与FROM区进行copy,保证了全部的对象都在FROM区内
缺点: a)浪费了50%的空间
b)要保证新生区的存活率很低
3).标记清除算法 通常用于老年区 , 分为两个部分一是标记部分 并且标记部分须要中止程序的运行过程,也须要扫描整个区
二是清除完的对象不必定是连续的,若是在从新分配空间时,不给分配连续的内存空间,则会显得不规整,因此jvm须要为他们找到连续的内存空间,费时费力 并且会产生碎片
4).标记清除压缩:在上一个方法的基础上进行了对应的提高,不须要jvm再寻找连续的内存空间,直接进行滑动便可,jvm只须要拥有一个内存的起始点便可
3.MySql的隔离机制
Read Uncmmitted(未提交的读取):
Read committed(已提交的读取):
Repeatable Read(可重复读取):
Seriazialiable(实现序列化):
day06 Mysql高级
1.索引:在数据以外,数据库系统还维护着知足特定算法查询数据的方法,便是索引,索引是一种用来查询数据的数据结构
2.如何高效的查询数据的算法结构
方法一:利用所有遍历的方法来查询,效率过低
方法二:高速查询的两种方法
a)利用Hash值来进行查询,由于hash值的惟一性,因此在进行crud等操做时都有着良好的表现,可是一旦要进行批量的查询数据,例如模糊查询,就会显示出该方法的一种劣势,由于他的hash值是惟一的,因此在进行批量查询时,反而比较麻烦他的总体平均时间复杂度会由O(1)升为O(n)
b)利用树结构进行查询的话,能够方便许多,避免了上面的问题的出现,他的平均时间复杂度会变为O(log2N)
注:Innodb并不支持Hash索引
3.平衡二叉树:由于普通的二叉树可能会产生一种一遍倾倒的现象,所以出现了平均二叉树,解决了上述问题。
缺点:因为会产生较高的树长,因此会在磁道上面留下许多IO,这样很不利于磁道的工做。
4.BTree的工做原理(2-3树):容许每一个磁盘块上(每一个节点上)有两个升序排列的关键字,三个用来存放下一个子节点的地址指针,在查找时,经过每一次的在磁块上的操做,
day07
1.Mysql的高级索引结构
单值索引:即一个索引只包含一个列,而一个表能够有多个单列索引
惟一索引:索引列的值必须惟一,可是能够为空
复合索引:即一个索引能够包含多个列
2.在mysql中使用的引擎为Innodb
3.mysql中经常使用的七种join语句分别为:
a)内链接:select * from A inner join B where A.id=B.id用来查询两个表中的公共部分
b)左外链接:select * from A left join B on A.id=B.id 将左表 当作主表 查询左边表的独有部分和两个表的公共部分
c)右外链接:select * from A right join B on A.id=B.id将右表 当作主表 查询右边表的独有部分和两个表的公共部分
d)A的独有部分的查询:select * from A left join B on A.id=B.id where B.id is null;
e)B 的独有部分:select * from A left join B on A.id=B.id where A.id is null;
f)全查询:两个表的全部部分都进行查询,在mysql中并不支持full的所有查询表,因此只能使用union的链接方法进行查询的链接
SELECT * FROM tbl_emp A LEFT JOIN tbl_dept B ON A.deptId = B.id
UNION
SELECT * FROM tbl_emp A RIGHT JOIN tbl_dept B ON A.deptId = B.id
4.索引与数据查询分析
索引解释:至关于将数据提早取出来放在一个固定的位置,方便了取数据。mysql 的索引结构是B+树
5.建立索引的方法:CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length));
ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
在优化mysql的过程当中,由许多的参数须要进行优化:
a) id:用来表示mysql执行过程当中的语句执行过程
1)id不一样的话,id越大则越早执行
2)id相同的话,则从上到下执行
b) select-type:行 查询的类型,主要是用于区别普通查询,联合查询,子查询等复杂查询
c) table:表示当前查询的属于哪一张表的
d) type表示访问类型:通常来讲用【system>const>eq_ref>ref>range>index>All】在平时的工做中能够达到ref级别已经很是不错了
e) possiables_keys:可能用到的索引,一个或者多个,可是不必定使用,
f) key:表示已经使用了的索引,若是该项为null,则说明并未使用索引,若是使用了索引覆盖,则该项的值与select的值相同。
g) ket_len:表示索引使用的字节数,在不丢失精度的状况下,长度越小越好。
h) ref显示索引的哪一列被引用了。
j) rows 根据表统计信息及索引用状况,大体估算出找到所需的记录所须要读取的行数
Condition
1.Condition 接口描述了可能会与锁有关联的条件变量。这些变量在用 法上与使用 Object.wait 访问的隐式监视器相似,但提供了更强大的 功能。须要特别指出的是,单个 Lock 可能与多个 Condition 对象关 联。为了不兼容性问题,Condition 方法的名称与对应的 Object 版 本中的不一样。
2.在 Condition 对象中,与 wait、notify 和 notifyAll 方法对应的分别是 await、signal 和 signalAll。
3.Condition 实例实质上被绑定到一个锁上。要为特定 Lock 实例得到 Condition 实例,请使用其 newCondition() 方法。