美文网首页
多线程第三阶段课程

多线程第三阶段课程

作者: jiahzhon | 来源:发表于2020-11-16 10:46 被阅读0次

    实现线程的方式

    • 继承Thread类

    • 实现Runnable接口

    • ExecutorService、Callable、Future有返回值的线程。

      • 有返回值的任务必须实现Callable接口,类型的,无返回值的任务必须实现Runnable接口。执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object了,再结合线程池接口ExecutorService就可以实现有返回结果的多线程。


        1
    • 基于线程池的方式


      2
    • CAS算法

      • CAS是靠硬件实现的,从而在硬件层面提升效率。
      • 实现过程
        • 假如现在有两个线程t1,t2,,他们各自的运行环境中都有共享变量的副本V1、V2,预期值E1、E2,预期主存中的值还没有被改变,假设现在在并发环境,并且t1先拿到了执行权限,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次发起尝试,然后t1比较预期值E1和主存中的V,发现E1=V,说明预期值是正确的,执行N1=V1+1,并将N1的值传入主存。这时候贮存中的V=21,然后t2又紧接着拿到了执行权,比较E2和主存V的值,由于V已经被t1改为21,所以E2!=V,t2线程将主存中已经改变的值更新到自己的副本中,再发起重试;直到预期值等于主存中的值,说明没有别的线程对旧值进行修改,继续执行代码,退出。


          20181122105801128.png
      • 结论
        • 其实就是拿副本中的预期值与主存中的值作比较,如果相等就继续替换新值,如果不相等就说明主存中的值已经被别的线程修改,就继续重试。
        • CAS(比较并交换)是CPU指令级的操作,只有一步原子操作,所以非常快。而且CAS避免了请求操作系统来裁定锁的问题,不用麻烦操作系统,直接在CPU内部就搞定了。

    CountdownLatch和CyclicBarrier不同

    • CountDownLatch不能reset,而CyclicBarrier是可以循环使用的。
    • CountDownLatch工作线程之间互不关心,而CyclicBarrier必须等到同一个共同的点才去执行某个动作。

    Executor

    • 线程池四种分类
      • newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
      • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
      • newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
      • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
    • ThreadPoolExecutor线程池的关闭
      • shutdownNow:线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行。
      • shutdown:线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。
      • 优雅地关闭线程池:
        • 使用shutdownNow方法,可能会引起报错,使用shutdown方法可能会导致线程关闭不了。所以当我们使用shutdownNow方法关闭线程池时,一定要对任务里进行异常捕获。
        • 当我们使用shuwdown方法关闭线程池时,一定要确保任务里不会有永久阻塞等待的逻辑,否则线程池就关闭不了。
        • 最后,一定要记得,shutdownNow和shuwdown调用完,线程池并不是立马就关闭了,要想等待线程池关闭,还需调用awaitTermination方法来阻塞等待。
    • 拒绝策略
      • 当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略。
      • CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
      • AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
      • DiscardPolicy - 直接丢弃,其他啥都没有。
      • DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入。

    相关文章

      网友评论

          本文标题:多线程第三阶段课程

          本文链接:https://www.haomeiwen.com/subject/sgeabktx.html