From d3a8322ca2613d94e1fb359381468a460c8905a9 Mon Sep 17 00:00:00 2001 From: hahaxw <41655980+hahaxw@users.noreply.github.com> Date: Thu, 4 Jun 2020 20:24:41 +0800 Subject: [PATCH] Create mayiketang --- mayiketang | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 mayiketang diff --git a/mayiketang b/mayiketang new file mode 100644 index 00000000..341a95ad --- /dev/null +++ b/mayiketang @@ -0,0 +1,165 @@ +1.并发包 +(1)、CountDownLatch +CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。 +(2)、CyclicBarrier +CyclicBarrier初始化时规定一个数目,然后计算调用了CyclicBarrier.await()进入等待的线程数。当线程数达到了这个数目时,所有进入等待状态的线程被唤醒并继续。 + CyclicBarrier就象它名字的意思一样,可看成是个障碍,所有的线程必须到齐后才能一起通过这个障碍。 +CyclicBarrier初始时还可带一个Runnable的参数, 此Runnable任务在CyclicBarrier的数目达到后,所有其它线程被唤醒前被执行。 +(3)Semaphore +Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态。它的用法如下: +availablePermits函数用来获取当前可用的资源数量 +wc.acquire(); //申请资源 +wc.release();// 释放资源 +2、并发队列 +(1)、ConcurrentLinkedQueue +ConcurrentLinkedQueue:是一个适用于高并发场景下的队列,通过无锁的方式,实现了高并发状态下的高性能,通常ConcurrentLinkedQueue性能好于BlockingQueue.它是一个基于链接节点的无界线程安全队列。该队列的元素遵循先进先出的原则。头是最先加入的,尾是最近加入的,该队列不允许null元素。 +ConcurrentLinkedQueue重要方法:add 和offer() 都是加入元素的方法(在ConcurrentLinkedQueue中这俩个方法没有任何区别)poll() 和peek() 都是取头元素节点,区别在于前者会删除元素,后者不会。 +(2)、BlockingQueue +BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种: +1. 当队列满了的时候进行入队列操作 +2. 当队列空了的时候进行出队列操作 +因此,当一个线程试图对一个已经满了的队列进行入队列操作时,它将会被阻塞,除非有另一个线程做了出队列操作;同样,当一个线程试图对一个空队列进行出队列操作时,它将会被阻塞,除非有另一个线程进行了入队列操作。 + +(3) ArrayBlockingQueue +ArrayBlockingQueue是一个有边界的阻塞队列,它的内部实现是一个数组。有边界的意思是它的容量是有限的,我们必须在其初始化的时候指定它的容量大小,容量大小一旦指定就不可改变。 +ArrayBlockingQueue是以先进先出的方式存储数据,最新插入的对象是尾部,最新移出的对象是头部。下面 +(4)LinkedBlockingQueue +LinkedBlockingQueue阻塞队列大小的配置是可选的,如果我们初始化时指定一个大小,它就是有边界的,如果不指定,它就是无边界的。说是无边界,其实是采用了默认大小为Integer.MAX_VALUE的容量 。它的内部实现是一个链表。 +(5) PriorityBlockingQueue +PriorityBlockingQueue是一个没有边界的队列,它的排序规则和 java.util.PriorityQueue一样。需要注意,PriorityBlockingQueue中允许插入null对象。 +所有插入PriorityBlockingQueue的对象必须实现 java.lang.Comparable接口,队列优先级的排序规则就是按照我们对这个接口的实现来定义的。 +另外,我们可以从PriorityBlockingQueue获得一个迭代器Iterator,但这个迭代器并不保证按照优先级顺序进行迭代。 +(6)SynchronousQueue +SynchronousQueue队列内部仅允许容纳一个元素。当一个线程插入一个元素后会被阻塞,除非这个元素被另一个线程消费。 +3、线程池 + (1)线程池的好处 +第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 +第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。 +第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源, +还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用 +线程池,必须对其实现原理了如指掌。 + java线程池的核心走ThreadPoolExecutor +(2)线程池的4种使用方式 +newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 +newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 +newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 +newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 +(3)在使用匿名内部内时,传入匿名内部类中的变量需要是final类型的变量,从jdk1.7以后做了修改,只要这个变量不能超过两次赋值包括两次,也就是只赋值了一次,jdk就会当做一个fianl类型的变量;所有可以使用一个中间变量来解决final的问题。 +(4)线程池运行原理 +提交一个任务到线程池中,线程池的处理流程如下: +1、判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个流程。 +2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则进入下个流程。 +3、判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。 + +(5)合理配置线程数 + CPU密集:线程执行短马上返回且执行频繁;线程池数量 = CPU核数 +IO密集:比如操作数据库需要IO等待、阻塞、休眠;线程池数据 = 2*CPU核数。 + (6)悲观锁与乐观锁 +悲观锁:悲观锁悲观的认为每一次操作都会造成更新丢失问题,在每次查询时加上排他锁。 +Select * from xxx for update; +乐观锁:乐观锁会乐观的认为每次查询都不会造成更新丢失,利用版本字段控制 + (7)重入锁 +锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。这些已经写好提供的锁为我们开发提供了便利。 +重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。 + +(8)读写锁 +相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些。假设你的程序中涉及到对一些共享资源的读和写操作,且写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写(译者注:也就是说:读-读能共存,读-写不能共存,写-写不能共存)。这就需要一个读/写锁来解决这个问题。Java5在java.util.concurrent包中已经包含了读写锁。尽管如此,我们还是应该了解其实现背后的原理。 + (3)CAS +CAS算法的过程是这样:它包含三个参数CAS(V,E,N): V表示要更新的变量(内存值),E表示预期值(原值),N表示新值。仅当V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做了更新,则当前线程什么都不做。最后,CAS返回当前V的真实值。 +4.JAVA反射机制和SpringIOC + (1)什么是JAVA反射机制 + 就是正在运行,动态获取这个类的所有信息。 +(2)反射机制的作用 + 1,反编译:.class-->.java + 2.通过反射机制访问java对象的属性,方法,构造方法等; +(3)反射机制的应用场景 +Jdbc 加载驱动、Spring ioc、框架 + (4)怎样禁用JAVA反射机制 + 将构造函数私有化。 + (5)使用java反射机制的几种api + 1.使用类的完整路径获取java类 +Class forName = Class.forName("com.itmayiedu.User"); + 2.创建无参构造函数对象:forName.newInstance(); +3.创建有参构造函数对象: +Constructorconstructor=forName.getConstructor(String.class,String.class); +User user = (User)constructor.newInstance("20","方方"); +4.获取所有属性:Field[] fields = forName.getDeclaredFields(); +5.获取所有方法: +Method[] declaredMethods = forName.getDeclaredMethods(); +6.给私有属性赋值 +Object newInstance = forName.newInstance(); +Field id = forName.getDeclaredField("id"); +id.setAccessible(true);//开启赋值权限 +id.set(newInstance,"30");// 将newInstance类的id属性赋值 + + (6)什么是SpringIOC +就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理。 + (7)SpringIOC底层原理 +1.读取bean的XML配置文件 +2.使用beanId查找bean配置,并获取配置文件中class地址。 +3.使用Java反射技术实例化对象 +4.获取属性配置,使用反射技术进行赋值。 +详细步骤如下: +1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象 +2.对于Document对象获取根元素对象后对下面的标签进行遍历,判断是否有符合的id. +3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象. +4.遍历标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理. +5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值. +6.返回建立的对象,如果没有对应的id,或者下没有子标签都会返回null +5、自定义注解与Java设计模式 + (1) @Target +@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。 +1. CONSTRUCTOR:用于描述构造器 +2. FIELD:用于描述域 +3. LOCAL_VARIABLE:用于描述局部变量 +4. METHOD:用于描述方法 +5. PACKAGE:用于描述包 +6. PARAMETER:用于描述参数 +7. TYPE:用于描述类、接口(包括注解类型) 或enum声明 +(2)@Retention +表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效) +(3)设计模式的分类 +总体来说设计模式分为三大类: +创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 +结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。 +行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。 +其实还有两类:并发型模式和线程池模式 + (4) 代理模式 +静态代理(静态定义代理类) +动态代理(动态生成代理类) +Jdk自带动态代理 +Cglib 、javaassist(字节码操作库) +(5)CGLIB与JDK动态代理区别: +java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。 +1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP +2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP +3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换 +6、sockket网络通讯 + (1) TCP与UDP在概念上的区别: +udp: a、是面向无连接, 将数据及源的封装成数据包中,不需要建立连接 + b、每个数据报的大小在限制64k内 + c、因无连接,是不可靠协议 + d、不需要建立连接,速度快 +tcp: a、建议连接,形成传输数据的通道. + b、在连接中进行大数据量传输,以字节流方式 + c 通过三次握手完成连接,是可靠协议 + d 必须建立连接m效率会稍低 + (2) tcp协议 +TCP握手协议 +在TCP/IP协议中,TCP协议采用三次握手建立一个连接。 +第一次握手:建立连接时,客户端发送SYN包(SYN=J)到服务器,并进入SYN_SEND状态,等待服务器确认; +第二次握手:服务器收到SYN包,必须确认客户的SYN(ACK=J+1),同时自己也发送一个SYN包(SYN=K),即SYN+ACK包,此时服务器V状态; +第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ACK=K+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 +完成三次握手,客户端与服务器开始传送数据, +四次分手: +由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。 +(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。 +(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。 +(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。 +(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。 + + + + + +

AltStyle によって変換されたページ (->オリジナル) /