`

Concurrent - 并发框架

 
阅读更多

原创转载请注明出处:http://agilestyle.iteye.com/blog/2356899

 

SynchronizedMap和ConcurrentHashMap有什么区别?

后者具有更高的并发

SynchronizedMap锁的是整个对象

ConcurrentHashMap锁的是段
...   
   /**
     * Maps the specified key to the specified value in this table.
     * Neither the key nor the value can be null.
     *
     * <p>The value can be retrieved by calling the {@code get} method
     * with a key that is equal to the original key.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with {@code key}, or
     *         {@code null} if there was no mapping for {@code key}
     * @throws NullPointerException if the specified key or value is null
     */
    public V put(K key, V value) {
        return putVal(key, value, false);
    }

    /** Implementation for put and putIfAbsent */
    final V putVal(K key, V value, boolean onlyIfAbsent) {
        if (key == null || value == null) throw new NullPointerException();
        int hash = spread(key.hashCode());
        int binCount = 0;
        for (Node<K,V>[] tab = table;;) {
            Node<K,V> f; int n, i, fh;
            if (tab == null || (n = tab.length) == 0)
                tab = initTable();
            else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
                if (casTabAt(tab, i, null,
                             new Node<K,V>(hash, key, value, null)))
                    break;                   // no lock when adding to empty bin
            }
            else if ((fh = f.hash) == MOVED)
                tab = helpTransfer(tab, f);
            else {
                V oldVal = null;
                synchronized (f) {
                    if (tabAt(tab, i) == f) {
                        if (fh >= 0) {
                            binCount = 1;
                            for (Node<K,V> e = f;; ++binCount) {
                                K ek;
                                if (e.hash == hash &&
                                    ((ek = e.key) == key ||
                                     (ek != null && key.equals(ek)))) {
                                    oldVal = e.val;
                                    if (!onlyIfAbsent)
                                        e.val = value;
                                    break;
                                }
                                Node<K,V> pred = e;
                                if ((e = e.next) == null) {
                                    pred.next = new Node<K,V>(hash, key,
                                                              value, null);
                                    break;
                                }
                            }
                        }
                        else if (f instanceof TreeBin) {
                            Node<K,V> p;
                            binCount = 2;
                            if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                           value)) != null) {
                                oldVal = p.val;
                                if (!onlyIfAbsent)
                                    p.val = value;
                            }
                        }
                    }
                }
                if (binCount != 0) {
                    if (binCount >= TREEIFY_THRESHOLD)
                        treeifyBin(tab, i);
                    if (oldVal != null)
                        return oldVal;
                    break;
                }
            }
        }
        addCount(1L, binCount);
        return null;
    }
...

Note:

ConcurrentHashMap 的结构示意图

ConcurrentHashMap 在默认并发级别会创建包含 16 个 Segment 对象的数组。每个 Segment 的成员对象 table 包含若干个散列表的桶。每个桶是由 HashEntry 链接起来的一个链表。如果键能均匀散列,每个 Segment 大约守护整个散列表中桶总数的 1/16。

 

CopyOnWriteArrayList可以用于什么应用场景?

多读少写

...    
   /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

    /**
     * Inserts the specified element at the specified position in this
     * list. Shifts the element currently at that position (if any) and
     * any subsequent elements to the right (adds one to their indices).
     *
     * @throws IndexOutOfBoundsException {@inheritDoc}
     */
    public void add(int index, E element) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            if (index > len || index < 0)
                throw new IndexOutOfBoundsException("Index: "+index+
                                                    ", Size: "+len);
            Object[] newElements;
            int numMoved = len - index;
            if (numMoved == 0)
                newElements = Arrays.copyOf(elements, len + 1);
            else {
                newElements = new Object[len + 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index, newElements, index + 1,
                                 numMoved);
            }
            newElements[index] = element;
            setArray(newElements);
        } finally {
            lock.unlock();
        }
    }
...

 

如何合理的配置Java线程池?如CPU密集型的任务,基本线程池应该配置多大?IO密集型的任务,基本线程池应该配置多大?用有界队列好还是无界队列好?任务非常多的时候,使用什么阻塞队列能获取最好的吞吐量?

要想合理的配置线程池,就必须首先分析任务特性,可以从以下几个角度来进行分析:

 

任务的性质:CPU密集型任务,IO密集型任务和混合型任务。

任务的优先级:高,中和低。

任务的执行时间:长,中和短。

任务的依赖性:是否依赖其他系统资源,如数据库连接。

任务性质不同的任务可以用不同规模的线程池分开处理。

  • CPU密集型任务配置尽可能少的线程数量,如配置Ncpu+1个线程的线程池。
  • IO密集型任务则由于需要等待IO操作,线程并不是一直在执行任务,则配置尽可能多的线程,如2*Ncpu。
  • 混合型的任务,如果可以拆分,则将其拆分成一个CPU密集型任务和一个IO密集型任务,只要这两个任务执行的时间相差不是太大,那么分解后执行的吞吐率要高于串行执行的吞吐率,如果这两个任务执行时间相差太大,则没必要进行分解。我们可以通过Runtime.getRuntime().availableProcessors()方法获得当前设备的CPU个数。

优先级不同的任务可以使用优先级队列PriorityBlockingQueue来处理。它可以让优先级高的任务先得到执行,需要注意的是如果一直有优先级高的任务提交到队列里,那么优先级低的任务可能永远不能执行。

 

执行时间不同的任务可以交给不同规模的线程池来处理,或者也可以使用优先级队列,让执行时间短的任务先执行。

 

依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,如果等待的时间越长CPU空闲时间就越长,那么线程数应该设置越大,这样才能更好的利用CPU。

 

建议使用有界队列,有界队列能增加系统的稳定性和预警能力,可以根据需要设大一点,比如几千。有一次我们组使用的后台任务线程池的队列和线程池全满了,不断的抛出抛弃任务的异常,通过排查发现是数据库出现了问题,导致执行SQL变得非常缓慢,因为后台任务线程池里的任务全是需要向数据库查询和插入数据的,所以导致线程池里的工作线程全部阻塞住,任务积压在线程池里。如果当时我们设置成无界队列,线程池的队列就会越来越多,有可能会撑满内存,导致整个系统不可用,而不只是后台任务出现问题。当然我们的系统所有的任务是用的单独的服务器部署的,而我们使用不同规模的线程池跑不同类型的任务,但是出现这样问题时也会影响到其他任务。

http://ifeve.com/thread-pools/

http://ifeve.com/java-threadpool/

 

  • 大小: 93.7 KB
  • 大小: 21.4 KB
分享到:
评论

相关推荐

    concurrent-1.3.4.jar

    线程池:concurrent包提供了Executor框架,可以方便地创建和管理线程池,从而更好地控制并发线程的数量,避免线程创建和销毁的开销。 同步工具类:concurrent包提供了一些同步工具类,如CountDownLatch、...

    Java-并发(Concurrent)编程

    资源概要:1,多线程;2,synchronized;3,volatile;4,多线程在JVM中的实现原理剖析 导语: 什么是多线程? 多线程(multithreading...并发工具类、并发容器、阻塞队列 线程池原理剖析 线程池案例-Web容器-压力测试

    无锁并行框架Amino -- Concurrent Building Blocks

    无锁并行框架Amino -- Concurrent Building Blocks

    concurrent-merge-sort

    基本的Spring IoC框架。 3.使用日志记录。 相同算法有两种不同的实现方式来演示并发实现。 第一个是edu.ncsu.mhthakka.concurrent.callable.mergesort.CallableMergeSorter这是一个实现合并排序的类。 它使用java的...

    Java并发框架整理

    多线程从1.2到1.7各种接口使用及场景介绍。

    Concurrent-File-Editing

    并发文件编辑演示版登录创建新文档并添加新用户并发文件编辑开始项目安装MongoDB社区版在本地主机上运行mongod:8080克隆目录在终端中打开项目目录,然后使用npm install安装依赖项。 运行node app.js以运行应用程序...

    Windows并发编程指南 Concurrent Programming on Windows (english)part2

    Windows并发编程指南 Concurrent Programming on Windows (english)part2Joe Duffy是Microsoft公司.NET框架团队中并行扩展功能的技术主管、架构师以及奠基者,就职于Visual Studio部门。除了编写代码和管理开发团队...

    Windows并发编程指南 Concurrent Programming on Windows (english)

    Joe Duffy是Microsoft公司.NET框架团队中并行扩展功能的技术主管、架构师以及奠基者,就职于Visual Studio部门。除了编写代码和管理开发团队外,他还为团队定下了远景目标和长期策略。他当前的研究领域包括:函数式...

    业级超高并发与高可用架构实现 JUC高并发编程 Java.Util.Concurrent源码+原理解析

    Java.Util.Concurrent是在并发编程中很常用的实用工具类。此包包括了几个小的、已标准化的可扩展框架,以及一些提供有用功能的类,没有这些类,这些功能会很难实现或实现起来冗长乏味。课程从技术原理和细节上,进行...

    The java.util.concurrent Synchronizer Framework

    concurrent Synchronizer Framework,讲解整个并发框架的设计思路!

    Windows并发编程指南 Concurrent Programming on Windows (english)part3

    Joe Duffy是Microsoft公司.NET框架团队中并行扩展功能的技术主管、架构师以及奠基者,就职于Visual Studio部门。除了编写代码和管理开发团队外,他还为团队定下了远景目标和长期策略。他当前的研究领域包括:函数式...

    concurrent 多线程 教材

    j-concurrent 00 IBM developerWorks 中国 : Java 多线程与并发编程专题 02 Java 程序中的多线程 03 编写多线程的 Java 应用程序 04 如果我是国王:关于解决 Java编程语言线程问题的建议 (2) 05 构建Java并发...

    concurrent 摘自guava concurrent

    这个工程是为了学习guava concurrent中的AbstractFuture而建立的,里面有可以运行的例子,再配合我的博客:https://blog.csdn.net/o1101574955/article/details/82889851,可以看明白guava concurrent的基本设计思路...

    Java并发编程实战

    5.1.2 迭代器与Concurrent-ModificationException 5.1.3 隐藏迭代器 5.2 并发容器 5.2.1 ConcurrentHashMap 5.2.2 额外的原子Map操作 5.2.3 CopyOnWriteArrayList 5.3 阻塞队列和生产者-消费者模式 5.3.1 ...

    Python资源之浏览器自动化与仿真-多进程并发-异步

    4. pulsar:是一个 Python 事件驱动的并发框架,能够实现异步编程。 5. diesel:是一个 Python 的基于 Greenlet 的 I/O 框架,能够实现异步编程。 6. gevent:是一个基于协同程序的 Python 网络库,使用 greenlet ...

    Java高并发实战_java高并发_高并发_

    第7章主要介绍了高并发框架Akka的基本使用方法,并使用Ak:ka框架实现了 个简单的粒子群算法, 模拟超高并发的场景。第8章介绍了使用Eclipse进行多线程调试的方法, 并演示了通过Eclipse进行多线程调试重现ArrayList...

    JAVA并发编程-2-线程并发工具类

    本章主要介绍java.util.concurrent下给我们提供的线程并发工具类的作用和使用场景。 一、Fork/Join 1、分而治之与工作密取 Fork/Join框架体现了分而治之的思想,就是在必要的情况下,将一个大任务进行拆分(fork)成...

    Java 并发编程实战

    5.1.2 迭代器与Concurrent-ModificationException 5.1.3 隐藏迭代器 5.2 并发容器 5.2.1 ConcurrentHashMap 5.2.2 额外的原子Map操作 5.2.3 CopyOnWriteArrayList 5.3 阻塞队列和生产者-消费者模式 5.3.1 ...

    J.U.C-AQS框架同步组件之闭锁CountDownLatch介绍

    CountDownLatch是在java1.5被引入的,跟它一起被引入的并发工具类还有CyclicBarrier、Semaphore、ConcurrentHashMap和BlockingQueue,它们都存在于java.util.concurrent包下。CountDownLatch这个类能够使一个线程...

    java中的线程并发库-----javaconcurrent探秘

    我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常需要有程序员独立完成代码实现,当然也有一些开源的框架提供了这些功能,但是这些依然没有JDK自带的功能使用起来方便。而当针对高质量Java多线程并发程序...

Global site tag (gtag.js) - Google Analytics