javase篇

作者: 青楼楼长 | 来源:发表于2019-11-18 10:31 被阅读0次

    异常:程序要么正常结束要么按照另一种方式也就是抛出错误,结束程序,异常有一个顶层接口throwable,下面有两个实现类Exception和error,Exception是可处理的可以分为可以检查(i/o这种(是必须要通过try catch处理的))的和运行时的异常(空指针呀,除数为0呀这种。这种坑定是程序员的错误),error是不可处理的,还有就是处理的方式:手动抛出throw,throws申明告知可能会抛出的异常,还可以try catch处理掉。

    反射:原理就是在程序运行的过程中动态的获取类的属性和方法。它的任意一个对象可以访问它的属性和方法.应用场景在Person p = new Student();编译的时候是person处理,运行时要使用student的方法就需要用到反射,有Class:获取属性和方法,Field:用来获取成员属性,Method:用来获取方法,Constructor:用来获取类的构造方法。可以通过是哪种方式全类名,对象.getclass,类.class,获取到类对象,类对象有获取属性的方法getdeclare还有方法getmethod,getconstruct这些方法。通过反射创建对象的两种方式:clazz.newinstance(),还有就是构造器,里面可以传入参数的.class(如果是有参构造的话)

    注解:主要知道四个注解:target:表示范围 inherit:表示某个类型是被继承的,document是用来生成api用到的,retention是时间的长短。

    内部类:

    线程:创建方式有四种:thread,runnable,callable,线程池的创建方式,线程池的顶层接口是excutorService,excuter是一个执行线程的工具。线程池有四个(缓存Cache:有线程可用直接重用,没有就新建一个,缓存中超过60s没有使用的就删除掉,Fixed固定大小的线程池:就是没有可用线程的就放入等待队列,如果有线程销毁则需要新建线程维持固定大小,延迟执行的线程Scheduled:可设置线程的延迟或者定期执行,单线程池single:只有一个,销毁(遇到异常什么的话)需要补充一个),,线程的状态:新建new,ruanable就绪,运行runnable,阻塞blocked,死亡dead,他们之间的转换首先新建new一个线程调用start()方法进入runnalble状态,抢到cpu时间片进入running状态,进入blocked状态有三种一种是cpu轮到别的线程进入等待池(wait)    还有就是锁被其他线程抢了进入等锁池,还有就是调用了join,sleep方法等待之后从新进入runnable状态,这里注意一下(yield是让同级线程来抢占,调用谁的join就执行谁,执行完在继续执行)。最后就是线程结束:1正常结束(运行完),2外部强制结束可以使用一个布尔变量循环条件,并用volatile修饰(目的是保证同一时间只有一个线程可以修改)3,使用interrupt方法{这里有两种情况一种就是线程是阻塞的,代用interrupt,抛出inerrupt异常,break之后结束线程运行,一种是处于为阻塞的状态:使用isinterruppt他会把中断标志设置为true有点像第二种}-----在针对start和run说哈,start进入就绪,run表示正在运行,start可以不用等run结束(多线程下)

    锁:先说下乐观锁,认为读多写少,认为别人不会修改,一般比较版本号(一致就修改,不一致重新读),悲观锁认为写多读少,所以每次都认为会被修改所以,就每次都加锁(Java中的sychronized),还有就是自旋锁,说白了就是占着cpu资源不放,等到锁就直接执行,不让他在用户态和内核态进行转化(这种一般等所时间不长,也就是竞争不激烈的时候性能较高也称之为自旋),要是竞争激烈的话,等锁要等很久,那么这样性能倒不如进入阻塞状态,所以后面有个自适应的自旋锁好像是在jdk1.6之后,可以根据实际情况来自适应开不开启自旋锁。然后就是sychronized,是一种重量级的悲观锁,也是一种可重入锁,是不公平的锁(应为他会让进来的锁进行自旋,相对于其他正在队列等待的不公平),是一种比较重的锁,后面好像是在jdk1.6之后优化,自适应锁,锁消除,锁粗化,轻量级锁,偏向锁优化。reentrantLock,是实现了Lock接口,sychronized能做的它都能做,而且更强大,有锁中断(防止死锁),可以选择是不是公平的锁,非公平的锁效率要高一些,但是他和sychroized的区别就是需要手动释放锁,一般在finally,如果不释放的话就是死锁了。semophore和reentrantLock一样的他有的这也有,实现了可以轮询的锁请求,也有公平非公平的锁机制(构造方法中)。autoicInteger是一个原子类比如i++这种不是原子操作的,需要用sychronized进行同步,而且automicInteger是sychronized的好几倍性能上。可重入锁(也叫递归锁)意思就是外层函数获取了这个锁,内层函数仍然可以获取这个锁,像sychronized和reentrantedLock都是可重入锁 。还有就是读写锁读是不会造成数据混乱的,读是共享的,写锁是写的时候上的,这个读与写有jvm控制,我们只需要上锁。(共享锁和独占锁也是讲述的这个意思)。一共有四种状态:无锁---偏向锁-(单个线程的优化因为原子操作比轻量级锁操作少--)---轻量级锁(多个线程同步代码块)-----重量级锁(依赖于操作系统的锁),锁升级也是只能单向往重量级方向升级,没有降级。分段锁是一种思想分段加锁比如concurrentHashMap,最后是锁优化减少持有时间,减少粒度,锁分离,锁粗化(请求完之后立即释放),锁消除(编译的时候处理,有些犹豫编码不规范导致

    线程池:线程池的原理是重写了thread的start方法,不断传入runnable对象进来(这里不断获取runnable是从队列中获取的)具体过程实际上是调用start然后调用run继而调用runnable的run方法【这就是原理】。

    lambda表达式:就是一种简化的语法格式,只需要参数列表和方法体的的一种语法格式,lambda表达式的目标类型是函数式接口(就是接口里面只有抽象方法,有其他的默认实现方法也是一样的),作用和匿名内部类是一样的,那么他们的区别在哪里呢?1.匿名内部类可以创建任意接口的实例(不管有多少个抽象方法)也可以为普通类创建实例,而lambda表达式只能为一个抽象方法的接口(函数式接口)2.lambda表达式还可以调用接口的默认的方法(接口中有的话),但是匿名内部类就不行。

    枚举类:就是一个特殊的类,enum修饰和class,interface是一样的等级,可以实现一个或者多个接口,默认的继承类是java.lang.Enum而不是Object这个类,当然了就是默认继承的是Enum这个类,不是说枚举类就不是Object的子类的了。为什么会有这个类,没有这个类之前是手动创建变量来做的(这样做存在类型不安全,命名空间的容易混淆,打印输出不明确的问题)可以通过类名.枚举变量来获取值,有values()列举出所有的枚举值。如果实现了接口想要对不同的枚举值有不同的表现可以从新实现每个枚举值的方法语法就有点类似匿名内部类的语法了。

    系统类:System,RunTime,String,StringBuffer,StringBuilder,Math,Random(多线程环境下使用ThreadLocalRandom),而且想要实现真正的额随机(这里需要使用不同的种子【传参可以使用时间作为当前的种子】),Date(已过时推荐使用Calendar)

    集合篇:集合线性表性能分析,java提供的List就是一个线性表的接口,而ArrayList与LinkedList又是线性表的两种经典实现:基于数组的线性表和基于链表的线性表。Queue代表队列,Dqueue代表双端队列(就是可以作为队列使用也可以作为栈使用)。【由于数组以一块连续的内存区域来保存所有的元素,所以在随机访问时性能最好,内部以链表作为底层的插入删除的时候性能最好,总体来讲ArrayList的性能比LinkedList要好所以一般选择ArrayList】如果实在多线程的情况下一般是选择Collections将集合包装成线程安全的集合类

    集合篇:各map实现类的性能分析,hashmap与hashtable实现机制几乎一样,但是hashtable是一个古老的线程安全的集合,因此hashmap比hashtable要快,那为什么要使用treemap呢,treemap总是有序的,可以调用keyset取得set集合在调用toarray生成key数组,那么就可以使用二分在这个数组快速查找对象了,对于一般的应用场景我们选择hashmap,他就是为快速查询设计的如果需要一个总是排好序的map就可以使用treemap,linkedhashmap比hashmap要慢一点因为要维护链表来保持map中添加的顺序,当然了还有identityhashmap性能到没有什么出色的地方和hashmap基本相似的实现,只是不使用equals来判断而是用==,enummap性能是最好的但是只能使用同一个枚举类的枚举值作为key。关于hash表的负载因子(当前记录数/桶的数量)默认为0.75的问题,这个是其实时间和空间上的折中当然了你也可以选择调整根据实际的情况,为什么默认是0.75较高的负载可以降低所占空间但是会增加查询数据的时间开销,相反低的负载会提高查询性能但是会增加开销。

    泛型:一般都是在后面菱形,在方法声明上在返回值前面有菱形括号,其他都是在后面

    相关文章

      网友评论

          本文标题:javase篇

          本文链接:https://www.haomeiwen.com/subject/tacdmctx.html