java知识点总结

线程类:

 1.start是在主线程执行,run是新开启一个线程执行

 2. synchronized是对类的当前实例进行加锁,static synchronized是对类进行加锁.

     

pulbic class Something(){
         public synchronized void isSyncA(){}
         public synchronized void isSyncB(){}
         public static synchronized void cSyncA(){}
         public static synchronized void cSyncB(){}
     }

 

 

      x.isSyncA()与Static.classSyncA()不互相影响.

 3.yield()是做线程让步,把锁让出来,和其他线程一起继续竞争资源.

 4.join()让主线程等待子线程执行完毕之后才继续进行.

 5.interrupt()中断本线程.如果这个线程处于阻塞状态,isInterrupted会返回true,会抛出InterruptedException,如果处于运行状态,调用interrupt()只是重置标志位为false,并抛出异常.

每个线程都有一个与之相关联的 Boolean 属性,用于表示线程的中断状态(interrupted status)。中断状态初始时为 false;

 

concurrent:

    基于cas机制(compare and swap).基于硬件级别的控制.如果CAS有三个操作数:内存值V、旧的预期值A、要修改的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做并返回false

 

集合:

hashmap:key和value都可以为null.底层是数组加链表实现的. loadFactor默认是0.75,size默认是16,每次resize  size都翻倍,然后所有值再hash分配.遍历的时候entrySet效率比keySet高.

 因为每个entry节点保存的是链表,顺序访问,如果用keyset,首先得找到key,key又是保存在链表中的,遍历速度很慢.jdk1.8中如果链表节点数量大于8,转换成红黑树.

hashset:底层是hashmap实现的.

hashTable:HashTable默认的初始大小为11,之后每次扩充为原来的2n+1.

linkedhashMap:底层也是hashmap的实现,不过添加了Entry类型的header,tail的变量用来当作链表记录添加顺序,如果accessOrder标记为true,那么会按访问顺序排序.

TreeMap:底层是红黑树实现的.按key比较存放的,所以是有序的.

linkedhashSet:底层是linkedhashMap实现的.

concurrentMap:

        jdk1.7之前使用segment segments对象来实现map的,每个segment对象都有一个hashEntry[]数组对象.hashentry对象就是构成链表的节点对象.所及加锁的范围是一个segment对象.

        进行put操作的时候会先找到你属于那个segment对象,然后在segment对象的put方法里再hash寻找属于hashEntry[]数组的哪个位置.

        jdk1.8取消了segments对象,而是直接用Node[] 对象来实现.加锁的范围是加在每一个Node对象上.jdk1.8中如果链表节点数量大于8,转换成红黑树.

 

copyOnWriteArrayList:  内部结构也是用数组实现,不过加了修饰符volatile,增加删除操作都会加锁.遍历的时候只会遍历副本,所以是线程安全的.

copyOnWriteArraySet:底层是copyOnWriteArrayList实现的.

ConcurrentSkipListMap:数据结构如下图所示.跳表分为许多层(level),每一层都可以看作是数据的索引,这些索引的意义就是加快跳表查找数据速度。每一层的数据都是有序的,上一层数据是下一层数据的子集,并且第一层(level 1)包含了全部的数据;层次越高,跳跃性越大,包含的数据越少。跳表包含一个表头,它查找数据时,是从上往下,从左往右进行查找.底层通过cas来实现线程安全.

 

 

 

 

ArrayBlockingQueue:数组实现的线程安全的有界的阻塞队列,底层是数组,通过ReentrantLock和Condition来实现.put方法会阻塞,offer会返回true或者false,add通过offer实现,offer返回false抛出异常.

 

LinkedBlockingQueue:LinkedBlockingQueue是一个单向链表实现的阻塞队列。该队列按 FIFO(先进先出)排序元素,新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。它对头和尾(取和添加操作)采用两把不同的锁,所以吞吐量通常要高于基于数组的队列.

 

LinkedBlockingDeque:LinkedBlockingDeque是双向链表实现的双向并发阻塞队列。该阻塞队列同时支持FIFO和FILO两种操作方式,即可以从队列的头和尾同时操作(插入/删除)

ConcurrentLinkedQueue:通过 cas来实现线程安全的队列.

PriorityBlockingQueue:优先级阻塞队列,底层也是通过数组加ReentrantLock实现的,存入的数据用二分法排序插入来实现优先级.

 

 

锁 :

ReentrantLock:  

        通过CAS来对计算加1,如果其他线程要获取锁,计数器>1,那么就进入等待队列.

         在同一个时间点只能被一个线程锁持有;而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取.ReentraantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的.ReentrantLock中,包含了Sync对象;而且,Sync是AQS的子类;更重要的是,Sync有两个子类FairSync(公平锁)和NonFairSync(非公平锁)。ReentrantLock是一个独占锁,至于它到底是公平锁还是非公平锁,就取决于sync对象是"FairSync的实例"还是"NonFairSync的实例"。其它获取失败的线程会进入等待队列,直到被自己中断.

 

Condition:Condition的作用对锁进行更精确的控制.Condition类似Object对象.不过能进行更精确的控制.

 

             Object      Condition  
休眠          wait        await
唤醒个线程     notify      signal
唤醒所有线程   notifyAll   signalAll

   //一个lock能分出多个Condition,所以可以更精确的控制.   

final Lock lock = new ReentrantLock();
final Condition notFull  = lock.newCondition(); 
final Condition notEmpty = lock.newCondition(); 

 

 

LockSupport:  LockSupport.park(Thread)   ,unpark(Thread).和Thread.wait()的区别在于wait让线程阻塞前,必须通过synchronized获取同步锁.

CountDownLatch:先latch.await()阻塞,等待调用足够次数的countDown()之后会唤醒进程.

初始化的时候会初始化参数

CyclicBarrier:让多少个线程或者任务等待至barrier状态,才会继续执行.

Semaphore:总共有特定数量的资源,多个线程共同使用,如果资源不足会一直阻塞.

 

 

 

jdk线程池架构:

    HashSet是线程集合,work对应一个线程,线程池里有一个BlockQueue队列用来保存任务. corePoolSize代表核心池大小, maximumPoolSize代表最大池大小.

 -- 如果此时,线程池中运行的线程数量< corePoolSize,则创建新线程来处理请求。
 -- 如果此时,线程池中运行的线程数量> corePoolSize,但是却< maximumPoolSize;则仅当阻塞队列满时才创建新线程。

    

    线程池有四种状态:RUNNING,SHUTDOWN, STOP, TIDYING, TERMINATED

    线程池被一旦被创建,就处于RUNNING状态, 

    调用shutdown之后变成shutdown状态,未执行完的任务继续执行,执行完之后变成tidyinng状态

    调用shutdownNow之后变成stop状态 ,中断未处理完的任务,中断之后变成tidyinng状态

     tidyinn状态调用terminal之后变成terminal状态.

 

    线程池共包括4种拒绝策略,它们分别是:AbortPolicyCallerRunsPolicyDiscardOldestPolicyDiscardPolicy

AbortPolicy         -- 当任务添加到线程池中被拒绝时,它将抛出 RejectedExecutionException 异常。
CallerRunsPolicy    -- 当任务添加到线程池中被拒绝时,会在线程池当前正在运行的Thread线程池中处理被拒绝的任务。
DiscardOldestPolicy -- 当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。
DiscardPolicy       -- 当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

 

   ScheduledThreadPoolExecutor的性能要优于Timer,因为timer是单线程执行的.Timer类的调度是基于绝对的时间的,而不是相对的时间,因此Timer类对系统时钟的变化是敏感的

 

你可能感兴趣的:(ms,java,数据结构与算法)