进程与线程的相关总结
进程与线程的简单解释
进程: 基本的资源分配资源
线程: 最小调度单元
线程安全
线程安全是多线程编程时的计算机程序代码中的一个概念。在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。
线程安全问题大多是由全局变量及静态变量引起的,局部变量逃逸也可能导致线程安全问题。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
线程池的概念
多线程虽然能够提高系统运行效率,但是创建过多的线程反而会造成很大的负担(线程本身也占有内存,大量的线程回收也会给系统带来压力)
线程池可以让线程多次使用,避免大量重复的创建线程。
通俗点讲,当有工作来,就会向线程池拿一个线程,当工作完成后,并不是直接关闭线程,而是将这个线程归还给线程池供其他任务使用。
线程池的主要参数
- corePoolSize
线程池核心池的大小,简而言之就是线程池允许同时运行的最大线程数量
换个说法,线程池创建之后,线程池中的线程数为0,当任务过来就会创建一个线程去执行,直到线程数达到corePoolSize 之后,就会把到达的任务放在队列中。
- maximumPoolSize
表示最大能创建多少个线程。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前提是当前线程数小于maximumPoolSize; - keepAliveTime
表示某个线程空闲多长时间时停止,默认情况下只有在线程池中线程个数大于corePoolSize时才会起作用。
如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。
- unit
keepAliveTime的单位 - workQueue
一个阻塞队列,当线程池中的线程个数大于corePoolSize时,新来的任务便会加到该队列中等待,任务必须实现runnable接口。
1、ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
2、LinkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene;
3、SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene;
4、priorityBlockingQuene:具有优先级的无界阻塞队列;
阻塞队列详解
- theadFactory
线程工厂,用来创建线程 - handler
拒绝任务处理时的策略
任务提交至线程池的处理过程:
如果小于corePoolSize,则直接分配线程执行
否则,提交至等待队列
如果提交失败(队列已满),则直接提交到线程池分配线程执行
如果已达到线程池上线,即maximumPoolSize,则实施拒绝策略。
拒绝策略
1.AbortPolicy:丢弃当前任务,并抛出异常(默认)
2.CallerRunsPolicy:只要线程池未关闭,直接在调用者线程中运行当前任务,显然这样做不会真的丢弃任务,但是,任务提交线程的性能极有可能会急剧下降。
3.DiscardPolicy:直接丢弃,不做任何处理
4.DiscardOldestPolicy:放弃线程池中最晚的一个请求(即将运行但还未运行的一个请求),再次尝试当前任务
线程池的关闭
1.shutDown
并不会直接关闭线程池,而是等线程池中所有的线程,包括等待队列,全部运行结束后关闭线程,但不再接受新任务。
2.shutDownNow
立即关闭线程池,打断正在执行的任务,清空缓存队列,返回未执行的任务
runworker
线程工厂在创建线程thread时,将Woker实例本身this作为参数传入,当执行start方法启动线程thread时,本质是执行了Worker的runWorker方法。
具体参考
网友评论