当前位置:文档之家› Java架构师必备知识点(高级程序员教程必备)

Java架构师必备知识点(高级程序员教程必备)

Java架构师必备知识点(高级程序员教程)2019年3月一、并发编程1.线程安全:当多个线程访问某一个类(对象)时这个类始终都能表现出正确的行为,那么这个类(对象和方法)就是线程安全的。

2.synchronized:可以在任意对象以及方法上加锁,而加锁的这段代码称为"互斥区"或者"临界区"。

一个线程想要执行synchronized修饰的方法里的内容,首先是尝试获得锁,如果拿到锁,执行synchronized方法体里面的内容如果拿不到那么这个线程会不断的尝试获得这把锁,直到拿到为止,而且是多个线程去竞争这把锁。

3.多个线程多个锁:多个线程,每个线程都将可以拿到自己指定的锁,分别获得锁之后,执行synchronized方法体的内容,关键字synchronized获得的锁都是对象锁,而不是把一段代码(方法)当做锁,在静态方法上机上synchronized获得的锁为类级别的锁,表示锁定类。

4.对象锁的同步和异步:同步synchronized:同步就是共享,同步的目的是为了线程安全,对于线程安全需要满足两个特性:原子性(同步)、可见性。

异步asynchronized:异步就是独立,相互之间不受任何制约。

5.脏读:对于对象的同步和异步方法,我们在设计程序的时候,一定要考虑问题的整体,不然就会出现数据不一致错误,很经典的错误就是脏读(dityread)。

在我们对一个对象的方法加锁的时候,需要考虑业务的整体性,即为setValue和getValue方法同时加锁synchronized同步关键字保证(service)业务逻辑层的原子性,不然会出现业务逻辑错误。

6.synchronized锁重入:关键字synchronized拥有重入锁的功能,也就是在使用synchronized时,当一个线程得到一个对象的锁后,再次请求此对象时是可以再次得到该对象的锁。

7.出现异常,锁自动释放:对于web应用程序,异常释放锁的情况,如果不及时处理,很可能对应用程序业务逻辑产生严重的错误。

比如:现在执行一个队列任务,很多对象都去在等待一个对象正确执行完毕再释放锁,但是一个对象出现由于异常的出现,导致业务逻辑没有正常执行完毕,就是释放了锁,那么后面的对象执行的都是错误的业务逻辑。

8.synchronized代码块:使用synchronized声明的方法在某些情况下是有弊端的,比如:A线程方法调用一个时间很长的任务,那么B线程必须等待很长的时间才能执行,这样的情况下可以使用synchronized代码块去优化代码执行时间,也就是减小锁的时间。

synchronized可以使用任何object对象进行加锁,用法比较灵活,不要使用string的常量加锁,会出现死循环问题。

9.锁对象改变的问题:当使用一个对象进行加锁的时候,要注意对象本身发生改变的时候,那么持有的锁就不同,如果对象不发生改变,那么依然是同步的,即使是对象的属性发生了改变。

10.volatile关键字:volatile的作用主要是使变量在多个线程间可见,在java中每一个线程都有一块工作内存区,其中存放着所有线程共享的变量值的拷贝,当线程执行时,在自己的工作内存区中操作这些变量,为了存取一个共享的变量,一个线程通常先获取锁定并去清除它的工作内存区,把这些共享变量从所有线程的共享内存区中正确的装入到他所在的工作内存区中,当线程解锁时保证该工作内存区中变量的值写回到共享内存中。

一个线程可以执行的操作有:使用(use)、赋值(assign)、装载(load)、存储(store)、锁定(lock)、解锁(unlock)。

主线程可以执行的操作有:读(read)、写(write)、锁定(lock)、解锁(unlock),每个操作都是原子的。

volatile的作用是强制线程到主内存(共享内存)里去读取变量,而不去工作内存区读取,从而实现了多个线程间变量可见,也就是满足线程安全的可见性。

11.volatile关键字的非原子性:volatile关键字虽然有多个线程间的可见性,但不具备同步性(原子性),可以算的上是一个轻量级的synchronized,性能比synchronized强很多,不会造成阻塞,volatile只针对于多个线程可见的变量操作,并不能代替synchronized的同步功能。

如要实现原子性使用atomic类的系列对象,支持原子性操作,atomic只支持本身方法原子性,并不保证多个线程的原子性。

12.多线程通信wait和notify:线程是操作系统中独立的个体,但这些个体不经过处理就不能成为一个整体,线程间的通信就成为整体的比用方法之一,当线程存在线程指挥,系统间的交互性会更强大,在提高CPU利用率的同时还会使开发人员对线程任务在处理的过程中进行有效的把控和监督。

使用wait和notify方法实现线程间的通信,这两个方法都是object类的方法,java为所有的类都提供了这两个方法,wait和notify都必须配合synchronized关键字使用,wait方法释放锁,notify不释放锁。

13.使用wait和notify模拟queue:blockingqueue:它是一个队列,并且支持一个阻塞的机制,阻塞的放入和得到数据,要实现linkedblockingqueue的方法是put()和take(),put(anobject):把anObject放入blockingqueue,如果blockingqueue没有空间,则调用此方法的线程被阻断,直到blockingqueue里面有空间再继续。

take:取走blockingqueue里排在首位的对象,如果blockingqueue为空,阻断进入等待状态,直到blockingqueue里有新的方法加入。

14.ThreadLocal:线程局部变量,是一种并发访问变量的解决方案,与其synchronized等加锁的方式不同,ThreadLocal完全不提供锁,而使用空间换时间的手段,为每个线程提供变量的独立副本,以保证线程安全。

从性能上说,不具有绝对的优势,在并发不是很高的时候加锁的性能会更好,但作为一套完全与锁无关的线程安全解决方案,在高并发量或者激烈的场景,用ThreadLocal可以在一定程度上减少锁的竞争。

15.单例和多线程:单例模式最常见的是饿汉模式和懒汉模式,一个直接实例化对象,一个在调用方法时进行实例化对象,在多线程的模式中,考虑到性能和线程安全问题,一般选择最近经典的两种单例模式,在性能提高的同时,又保证了线程安全。

17.同步类容器:同步类容器都是线程安全的。

但在某些场景下加锁来保护复合操作,复合操作如:迭代(反复访问元素,遍历完容器中所有的元素)、跳转(根据指定的顺序找到当前元素的下一个元素),以及条件的运算,这些复合操作在多线程并发的修改容器时,可能会表现出意外的行为,最经典的便是concurrentmodificationException,原因是当容器迭代的过程中,被并发修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问题。

同步类容器:如:古老的vetor、hashtable这些容器的同步功能都是JDK 的conllections.synchronized等工厂方法去创建实现的,其底层的机制是传统的synchronized关键字对每个公用的方法都进行同步,使得每次只有一个线程访问容器的状态,这很明显不能满足互联网时代高并发的需求,在保证线程安全的同时,也必须有足够好的性能。

18.并发类容器:JDK1.5以后提供了多种并发类容器来替代同步类容器,从而来改善性能。

同步类容器的状态都是串行化的,他们虽然实现了线程安全,但是严重降低了并发性,严重降低了应用程序的吞吐量,并发类容器是专门针对并发设计的,使用concurrentMap来代替给予散列的传统的hashtable,而且在concurrentMap中,添加了一些常见复合操作的支持,以及使用了CopyOnWriteArrayList代替voctor,并发CopyOnWriteArraySet,以及并发的Queue,concurrentLinkedQueue和LinkedBlockingQueue,前者是高性能的队列,后者是以阻塞形式的队列,具体实现Queue还有很多,例如:ArraListBlockingQueue、priorityBlockingQueue、synchronousQueue等。

19.concurrentMap:concurrentMap接口有两中重要的实现:concurrentHashMap和concurrentSkipListMap,concurrentSkipListMap支持并发排序功能,弥补concurrentHashMap,concurrentHashMap内部使用段(segment)来表示不同的部分,每个段是一个小的hashtable,它们有自己的锁,只要多个修改操作发生在不同的段上就可并发执行,把一个整体分成16个段(segment),也就是最高支持16个线程的并发修改操作,这也是在多线程场景时减少锁的粒度,从而降低了锁竞争的一种方案,并且代码中大多共享变量使用volatile关键字声明,目的是第一时间获取修改的内容,性能好。

20.CopyOnWrite容器:简称COW,是一种程序设计的优化策略,JDK里的COW容器有两种:CopyOnWriteArrayList和CopyOnWriteArraySet,COW非常有用,可以在非常多的应用场景下使用到,CopyOnWrite容器是写时复制的容器,通俗的理解就是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将容器进行copy,复制一个新的容器,然后在新的容器里添加元素,添加完元素后再原容器的引用指向新的容器,这样做的好处是可以对CopyOnWrite容器进行并发的读,,而不需要加锁,因为当前容器不会添加任何元素,所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

CopyOnWrite在读多写少的应用场景下使用。

21.并发Queue:在并发队列上JDK提供了两套实现,一个是以concurrentLinkedQueue为代表的高性能队列,一个是以BlockingQueue接口为代表的阻塞队列,它们都继承Queue。

concurrentLinkedQueue:是一个适用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常concurrentLinkedQueue性能高于BlockingQueue,它是一个基于链接节点的无界线程安全队列,该队列的元素遵循先进先出的原则,头是最先加入的,尾是最近加入的,该队列不允许null元素。

相关主题