Java 进程和线程 2

线程池的工作原理

1.线程池判断核心线程池里的线程是否都在执行任务。如果不是,则创建一新的工作线程来执行任务。如果核心线程池里的线程都在执行任务,则执行第二步。

2.线程池判断工作队列是否已经满。如果工作队列没有满,则将新提交的任务存储在这个工作队列里进行等待。如果工作队列满了,则执行第三步。

3.线程池判断线程池的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务。如果已经满了,则交给饱和策略来处理这个任务。

构造器中参数含义:

1) corePoolSize

线程池中的核心数。当提交任务后,线程池创建一个新线程执行任务,真到当前线程数等于corePoolSize;如果当前线程数为corePoolSize,继续提交任务被保存到阻塞队列中,等待被执行。

2)maximumPoolSize

线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建的线程执行任务,前提是当前线程数小于maximumPoolSize;

3)keepAliveTime

线程空闲时的存活时间。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

4)unit

keepAliveTime参数的时间单位。

例如TimeUnit.DAYS

5)workQueue

任务缓存队列,用来存放等待执行的任务。如果当前线程数为corePoolSize,继续提交的任务就会被保存到任务缓存队列中,等待被执行。

BlockingQueue(阻塞队列)

SynchronousQueue(同步队列)一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。因此,如果线程池中始终没有空闲线程(任务提交的平均速度快于被处理的速度),可能出现无限制的线程增长。

LinkedBlockingQueue (链接阻止队列):基于链表结构的阻塞对列,如果不设置初始化容量,其容量Integer.MAX_VALUE,即为无界队列。因此,如果线程池中线程数达到了corePoolSize,且始终没有

空闲线程(任务提交的平均速度快于被处理的速度),任务缓存队列可能出现无限制的增长。

ArrayBlockingQueue(数组阻止队列):基于数组结构的有界阻塞队列,按FIFO排序任务

6.threadFactory 线程工厂,创建新线程时使用的线程工厂。

7.handler 任务拒绝策略,当阻塞队列满了,且线程池中的线程数达到maximumPoolSize,如果继续提交任务, 就会采取任务拒绝策略处理该任务,线程池提供了4种任务拒绝策略:

  • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常,默认策略;

  • CallerRunsPolicy:由调用execute方法的线程执行该任务;

  • DiscardPolicy:丢弃任务,但是不抛出异常;

  • DiscardOldestPolicy:丢弃阻塞队列最前面的任务,然后重新尝试执行任务(重复此过程)。

  • 当然也可以根据应用场景实现RejectedExecutionHandler接口自定义饱和策略,如记录日志或持久 化存储不能处理的任务。

守护线程

        正常情况下,非守护线程的执行时间和主线程无关,即使主线程已经结束,也不会影响子线程的运行。

        守护线程是为其它线程提供服务的线程

        守护进程的特点是当程序中主线程结束时,守护线程会自动中止

如何将一个子线程设置为守护线程

        在一个线程调用start启动之前,调用方法thread.setDaemon
 (true);就可以将thread线程设置为守护线程.

        守护线程一般应该是一个独立的线程,它的run()方法是一个无限
 循环

        守护线程与其它线程的区别是,如果守护线程是唯一运行着的线程,程序会自动退出

  • synchronized相对于volatile是重量级的线程安全的方法,可以保证3大特性:原子性、可见性、有序性。

    • 可以将并发操作转换为串型执行

    1同步代码块:

    2.同步方法(synchronized):在方法上添加同步关键字,当前的锁对象为当前对象no---对象锁。

    使用的是对象锁,所以只能new一个对象,才可以得到互斥的效果。如果创建多个则不能达到互斥的目的

3.同步静态方法,以当前类Class对象作为锁---类锁

使用类锁时,不管new了多少个对象,都可以得到互斥的效果。

如果使用不同锁多个线程不会实现互斥效果。

引入锁机制以解决线程安全问题:

  • 悲观锁:当存在多个线程操作共享数据时,需要保证同一时刻有且只有一个线程

  • 在操作共享数据,其他线程必须等到该线程处理完数据后再进行

  • 乐观锁:CAS compare and set

    synchronized总结

    synchronized同步关键字,用于代码同步处理,解决线程安全问题

synchronized同步方法 以当前对象充当锁

public synchronized void pp(){}

synchronized同步静态方法 以当前类Class充当锁

public synchronized static void pp(){}

synchronized同步代码块 自定义对象充当锁

synchronized(obj){}

synchronized原理

在添加synchronized关键字后就可以保证在一个时刻上只有一个线程在调用某个方法或

者代码块,不会出现并发的情形,达到排队执行的效果。

synchronized能够保证 原子性 可见性 有序性

volatile 原子性 可见性

jdk6之前是重量级锁,JDK6开始优化锁的状态总共有四种,无锁状态(使用乐观锁CAS,没有synchronized)、偏向锁、轻量级锁和质量级锁。锁状态的改变是根据竞争激烈程度进行的,在几乎无竞争的条件下,会使用偏向锁,在轻度竞争的条件下,会由偏向锁升级为轻量级锁,在重度竞争的条件下,会使用偏向锁,在轻度竞争的条件下,会由偏向锁升级为轻量级锁,再升级的重量级锁,但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级

对象在内存中存储时可以分为对象头、实例数据和对齐

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值