• 多线程用到的概念知识点


    http://ifeve.com/concurrenthashmap/

    并发编程网:

    concurrentHashMap:详细介绍

     1、实现原理:锁分段机制。

     concurrentHashMap ----> segment ---> hashEntry 

    将map分为多个数据段,每段数据只能由一个线程访问,当多个线程访问entry数据时,只锁住这个entry所在的段,其他段的数据 仍然可以被其他线程访问。

    2、好处: 在多线程情况下提高效率。

    3、在读取数据时,不需要加锁。

    valitile修饰变量 count 和value。 

    具有原子性和可见性。

    get操作的高效之处在于整个get过程不需要加锁,除非读到的值是空的才会加锁重读,我们知道HashTable容器的get方法是需要加锁的,那么ConcurrentHashMap的get操作是如何做到不加锁的呢?原因是它的get方法里将要使用的共享变量都定义成volatile,如用于统计当前Segement大小的count字段和用于存储值的HashEntry的value。定义成volatile的变量,能够在线程之间保持可见性,能够被多线程同时读,并且保证不会读到过期的值,但是只能被单线程写(有一种情况可以被多线程写,就是写入的值不依赖于原值),在get操作里只需要读不需要写共享变量count和value,所以可以不用加锁。之所以不会读到过期的值,是根据java内存模型的happen before原则,对volatile字段的写入操作先于读操作,即使两个线程同时修改和获取volatile变量,get操作也能拿到最新的值,这是用volatile替换锁的经典应用场景。

    put:需要加锁

    size不加锁,先将所有segment中的count值相加,然后再重复计算两次count值,若两次计算的值不一致,就将各个段都锁住,再进行计算。

    writeOnArrayList:

    http://ifeve.com/java-copy-on-write/

    相当于arraylist,应用于并发编程,每次写入数据都对元数据进行复制,写入成功后,再将原数据的引用指向新数据。

    使用与多次读操作。(注:每次读的是原来的数据。不能实时读)

    ExecutorService: 创建线程池:(4种创建方法)

    http://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice

    ThreadPoolExecutor:

    future 和futureTask:

    http://www.tuicool.com/articles/m26Vzm

            futrure可以返回一个任务的生命周期。

    runnable 不能返回值,能将数据写入文件。executor 实现了runnable

    callable能返回值,能抛出异常。

     Executor框架使用Runnable 作为其基本的任务表示形式。Runnable是一种有局限性的抽象,然后可以写入日志,或者共享的数据结构,但是他不能返回一个值。

    许多任务实际上都是存在延迟计算的:执行数据库查询,从网络上获取资源,或者某个复杂耗时的计算。对于这种任务,Callable是一个更好的抽象,他能返回一个值,并可能抛出一个异常。

    Future表示一个任务的周期,并提供了相应的方法来判断是否已经完成或者取消,以及获取任务的结果和取消任务。

    注:公司的console项目,多线程管理是通过继承Thread来执行任务的,将任务信息存储进ArrayBlockingQueue,并定时将任务queue中的数据写到数据库。
    完成多线程的管理。

            采集器的实现:启动一个多线程,轮询ThreadPoolExecutor的executor,查看线程池的执行情况:

    java中线程池的监控可以检测到正在执行的线程数。

    // 通过线程池提供的参数进行监控。线程池里有一些属性在监控线程池的时候可以使用

    // taskCount:线程池需要执行的任务数量。

    // completedTaskCount:线程池在运行过程中已完成的任务数量。小于或等于taskCount。

    // largestPoolSize:线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过。如等于线程池的最大大小,则表示线程池曾经满了。

    // getPoolSize:线程池的线程数量。如果线程池不销毁的话,池里的线程不会自动销毁,所以这个大小只增不- 

    // getActiveCount:获取活动的线程数。

    // 通过扩展线程池进行监控。通过继承线程池并重写线程池的beforeExecute,afterExecute和terminated方法,我们可以在任务执行前,执行后和线程池关闭前干一些事情。如监控任务的平均执行时间,最大执行时间和最小执行时间等。这几个方法在线程池里是空方法。如:

    // protected void beforeExecute(Thread t, Runnable r) { }

    System.out.println("monitor begin....");

    System.out.println(String.format(

    "[monitor] [%d/%d] Active: %d, Completed: %d, Task: %d, isShutdown: %s, isTerminated: %s",

    this.executor.getPoolSize(), this.executor.getCorePoolSize(), this.executor.getActiveCount(),

    this.executor.getCompletedTaskCount(), this.executor.getTaskCount(), this.executor.isShutdown(),

    this.executor.isTerminated()));


    ScheduledExecutorService 类,定时器类



  • 相关阅读:
    Struts2+Spring+Mybatis+Junit 测试
    struts2 action 页面跳转
    Java面试题(全)
    Java面试题
    Kubernets二进制安装(17)之安装部署Dashboard
    Kubernets二进制安装(16)之安装部署traefik(ingress)
    Kubernets二进制安装(15)之安装部署coredns
    Kubernets二进制安装(14)之flannel之SNAT规则优化
    Kubernets二进制安装(13)之部署Flannel
    Docker网络模型
  • 原文地址:https://www.cnblogs.com/yeemi/p/7470135.html
Copyright © 2020-2023  润新知