zoukankan      html  css  js  c++  java
  • JDK并发相关并发包

        synchronized的功能扩展:

        重入锁;ReentrantLock;

            其实也就是lock对于synchronized的替代了,要注意的一个点就是你可以锁多个,但是你锁了几个,最后就要解锁几个这个问题;

            使用lock.lock()加锁,使用lock.unlock()解锁;

        提供中断处理;

      使用中断锁,线程可以被中断,也就是说,当一个线程正在等待锁的时候,他依然可以收到一个通知,被告知无须等待,可以停止工作了,使用的是lock.lockInterruptibly();方法;

        锁申请等待限时;

      给锁给定一个时间,如果超过了这个时间的话,就让线程自动放弃;使用的是lock.trylock(时间段,时间单位);另外还有一个就是lock.trylock();如果是带参数的,就是最多等待这么多时间,超过了时间就返回false,成功获得了锁,就返回true;如果是不带参数直接运行,就是比较直接的,如果锁未被占用,则申请锁成功,返回true,否则就是失败了,直接返回false;

        公平锁;

            公平锁的一个特点就是:它不会产生饥饿现象;所有的锁都是先到先等,不得插队;但是维持公平需要一个有序队列,实现成本较高,性能相对也非常低下,默认情况下,锁是非公平的;

        以下是我们整理的几个重要方法:

            1,lock():获得锁,如果锁已经被占用,则等待;
            2,lockInterruptibly():获得锁,但优先响应中断;
            3,tryLock():尝试获得锁,如果成功,返回true,失败返回false,该方法不等待,立即返回;
            4,tryLock(Long time,TimeUnit unit):在给定的时间内尝试获得锁;
            5,unlock():释放锁;

        重入锁的好搭档:Condition条件;

    使用new Condition可以生成与当前重入锁绑定的Condition实例;使得我们可以让线程在合适的时间等待,或者在某一特定的时刻得到通知,继续执行;
            1,await();让当前线程等待,同时释放当前锁,作用上和wait()相似;
            2,awaitUninterruptibly();与await()方法基本相同,不会在等待过程中响应中断;
            3,singal();用于唤醒一个在等待中的线程,相对的singalAll()方法会唤醒所有在等待中的线程,和notify()类似;

        允许多个线程同时访问:信号量;

            只允许一个线程访问一个资源,而信号量则可以指定多个线程;
            public Semaphore(int permits)
            public Semaphore(int permits,boolean fair);第二个参数可以指定是否公平锁;
            这所谓的信号量,其实就是一个执行器啦,只是换了名字看不出来了而已。。。参数可以指定有多少个线程;

        ReadWriteLock读写锁;

    关于读写的问题,我们要明确的一点就是,我们可以对一个文件多次重复读取,但是当读与写发生冲突的时候,我们要做的就是保证他们的互斥了;
            读读不互斥;
            读写互斥;
            写写互斥;
        如果读的操作远远大于写的操作的话,读写锁就会发挥最大的功效;
        Lock readLock = readWriteLock.readLock();
        Lock writeLock = readWriteLock.writeLock();
        读线程完全并行,而写会阻塞读;

        倒计时器:CountDownLatch;

            此工具通常用来控制线程等待,让某一个线程等待知道倒计时结束,再开始执行;
            只有当你一开始设定的所有线程都跑完了,你这个倒计时器才算真正结束了;
            CountDownLatch end = new CountDownLatch(10);
            end.countDown();      
            当调用CountDownLatch.countDown()方法的时候,也就是通知CountDownLatch,一个线程已经完成了任务,倒计时器可以减1了;

        循环珊栏;CyclicBarrier;

            另外一种多线程并发控制实用工具;
                其实本质上跟倒计时器是差不多的功能类似,唯一的区别就在于可以反复使用,而且可以设置,当计数结束之后,系统下一步要执行的动作;
            public CyclicBarrier(int parties,Runnable barrierAction);
                其中barrierAction是执行的动作;

        线程阻塞工具类:LockSupport;

            可以在线程内任意位置让线程阻塞;和Thread.suspend()相比,弥补了由于resume()在前发生,导致线程无法继续执行的情况;
            与object.wait()相比,不需要先获得某个对象的锁,也不会抛出interruptedException异常;
            LockSupport.park();
            LockSupport.unpark(t1);
           除了有定时阻塞的功能外,LockSupport.park()还能支持中断影响;但是LockSuppor.park()不会抛出InterruptedException异常,他只是默默的返回; 
            也就是说:LockSupport.park()进行阻塞之后,如果中断这个线程,不会抛出异常,而是默默的返回;

        线程复用:线程池;

            我们在这里用到了池的概念来保存管理我们的线程;
            当我们要使用线程的时候,不是创建,而是从池子中去取,当我们要关闭线程的时候,是将这个线程返回给池子,方便其他人使用;

        JDK对线程池的支持;

             newFixedThreadPool(int nThreads);
             newSingleThreadExecutor();
             newCachedThreadTool();
             newSingleThreadScheduledExector();
             newScheduledThreadPool(int corePoolSize);
        newFixedThreadPool():该方法返回一个固定线程数量的线程池;线程池的数量保持不变,若线程池已满,新的任务会被暂存在一个任务队列中;
        newSingleThreadExecutor();该线程池只有一个线程在里面,多余任务会被保存到一个任务队列中;
        newCachedThreadPool();返回一个根据实际情况调整线程数量的线程池,也就是说,这个线程池中的线程是可以可调整的。当所有的线程都在工作而此时又有新的任务提交,则会扩展线程的数量;
        newSingleThreadScheduledExecutor();返回一个ScheduledExecutorService对象,在ExecutorService接口上扩展了在给定时间执行某任务的功能,
        newScheduledThreadPool()方法,可以指定线程数量和时间的线程池;

        核心线程池的内部实现;

            都是在原有的ThreadPoolExecutor()的基础上进行的参数设置和修改;
            而其实,这个ThreadPoolExecutor()内部的参数也有很多的;
            int corePoolSize;线程池中线程的数量;
            int maximumPoolSize;指定了线程池的最大线程数量;
            long keepAliveTime;当线程池数量超过了corePoolSize时吗,多与的空闲线程的存活时间;
            TimeUnit unit;keepAliveTime的时间单位;
            BlockingQueue<Runnable> workQueue:任务队列,被提交但尚未被执行的任务;
            ThreadFactory threadFactory;线程工厂,用于创建线程,一般用默认的;
            handler;拒绝策略,当任务太多来不及处理,如何拒绝任务;
        现在我们上面的几个线程池是如何通过ThreadPoolExecutor()以及内部的参数来设定的呢,我们现在就来说一下;
            其中newFixedThreadPool(nThreads,nThreads,0L,new LinkedBlockingQueue<Runnable>);
            newSingleThreadExecutor(1,1,0L,new LinkedBlockingQueue<Runnable>);
            newCachedThreadPool(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
            其中,我们可以看出,当newCachedThreadPool时,我们是指定线程池数量为0,但是最大线程数为无限,而且采用的任务队列跟上面的队列不一样,下面将重点说明这两种任务队列的不同之处;
            SynchronousQueue:这是直接提交的队列,每一个线程都会直接提交,不会真实地保存,而是直接将新任务交给线程执行器;
            ArrayBlockingQueue:这是有界的任务队列,需要带一个参数,表示该队列的最大容量;
            LinkedBlockingQueue:这是无界的任务队列,多余的任务会先放到这里;
            PriorityBlockingQueue:这是优先任务队列,根据任务自身的优先级顺序先后执行;

            不要重复发明轮子:JDK的并发容器;

                ConcurrentHashMap:高效的并发HashMap;
                CopyOnWriteArrayList:在读多写少的场合,这个List的性能非常好,远远好于Vector(另外。。Vector已经过时了,不用了);
                ConcurrentLinkedQueue:高效的并发队列,使用链表实现,可以看做一个线程安全的LinkedList;
                BlockingQueue:表示阻塞队列,详情可以查看一下生产者——消费者模式;
                ConcurrentSkipListMap:跳表的实现;这是一个Map,使用跳表的数据结构进行快速查找;
            以上并发容器的内部数据结构实现,我们在下一章会提到;敬请期待!
  • 相关阅读:
    ★★★5230打字慢的解决方法...绝对有用...只需要在手机上轻微的设置一下(转)
    IT公司中最流行的10种编程语言(转)
    Windows下安装Object C开发环境,及Hello Word(转)
    [图]AMD的CPU在VirtualBox中安装Mac OS X 10.6(转)
    How_to_Handle_Pointer_Events_in_a_Custom_Control(转)
    Cannot obtain license for Compiler (feature compiler) with license version >= 2.2(转)
    GNUstep Gorm第一个视窗程序,第一个图形界面,第一个helloworld gui(转)
    Symbian源码分析(转)
    Symbian计算MD5(转)
    Does not support program for platform "WINSCW"
  • 原文地址:https://www.cnblogs.com/zxx123/p/9736046.html
Copyright © 2011-2022 走看看