• Java读书笔记(4)-多线程(二)


    2016-1-2

    1. 线程通信

      • 传统的线程通信

        • Object类提供了wait()notify()notifyAll三个方法

        • 适用情况:synchronized修饰的同步方法或者synchronized方法

        • wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()notifyAll方法来唤醒该线程,调用wait方法后本线程会释放对同步监视器的锁定

        • notify():唤醒在此同步监视器上等待的单个线程。如果有多个线程在等待,则随机唤醒其中一个

        • notifyAll():唤醒在此同步监视器上等待的所有线程

      • 使用Condition控制线程通信

        • 适用于使用Lock对象来同步的场景,Condition实例被绑定在一个Lock对象

        • Lock替代了同步方法或同步代码块,Condition替代了同步监视器的功能

        • await(),signal(),signalAll()

        • private final Lock lock=new ReentrantLock();

        • private final Condition cond=lock.newCondition();

        • cond.await()

        • cond.signalAll()

      • 使用阻塞队列(BlockingQueue)控制线程通信

        • add(E e), off(E e), put(E e)

        • remove(), poll(), take()

        • element(), peek()

      • ArrayBlockinQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue, DelayQueue

      • BlockingQueue<Stirng> bq=new ArrayBlockingQueue<>(2);

        bg.put(“Java”)

    2. 线程组(ThreadGroup)和未处理的异常

        • 程序可以直接以组为单位控制线程

        • 线程运行途中不能更改所属线程组

        • ThreadGroup:activeCount(), interrupt(), isDaemon(), setDaemon(), setMaxPriority()

        • ThreadGroup内还定义了一个很有用的方法:void uncaughtException(Thread t,Throwable e), 可以处理线程组内任意线程所抛出的异常

        • 使用catch捕获异常时,异常不会传播给上一级调用者;但是使用异常处理器对异常进行处理后,异常依然会传播给上一级调用者

    3. 线程池

      • 当程序中需要创建大量生存期很短暂的线程时,应该考虑使用线程池。线程池在系统启动时即创建大量空闲的线程

      • Java5实现的线程池

        • 返回一个ExecutorService对象,该对象代表一个线程池:newCachedThreadPool()newFixedThreadPool(int nThreads),newSingleThreadExecutor()

        • new ScheduledThreadPool(int corePoolSize),new SingleThreadScheduledExecutor()

        • 使用线程池来执行线程任务的步骤:

          1. 调用Executors类的静态工厂方法来创建一个ExecutorService对象,该对象代表一个线程池;

          2. 创建Runnable实现类或Callable实现类的实例,作为线程执行任务;

          3. 调用ExecutorService对象的submit()方法来提交Runnable实例或者Callable实例;

          4. 任务执行完毕,最后关闭线程池shutdown()

      • Java7新增的ForkJoinPool

        • 充分利用多CPU,多核CPU的性能优势

        • 将一个任务拆分成多个“小任务”并行计算,再把多个小任务的结果合并成总的计算结果

        • ForkJoinPoolExecutorService的实现类,因此是一种特殊的线程池

        • 创建了ForkJoinPool实例之后,就可以调用ForkJoinPoolsubmit(ForkJoinTask task)或者invoke(ForkJoinTask task)方法来执行指定任务了。其中ForkJoinTask代表一个可以并行,合并的任务。ForkJoinTask是一个抽象类,它还有两个抽象子类:RecursiveActionRecursiveTask。其中RecursiveTask代表有返回值的任务,而RecursiveAction代表没有返回值的任务。

    4. 线程相关类

      • ThreadLocal

        • 代表一个线程局部变量,通过把数据放在ThreadLocal中就可以让每个线程创建一个该变量的副本

        • 在编写多线程代码时,可以把不安全的整个变量封装进ThreadLocal,或者把对象与线程相关的状态使用ThreadLocal保存

        • ThreadLocal类与线程同步机制面向的问题领域是不同的

        • 如果多个资源之间需要共享资源,以实现线程通信,则使用同步机制;如果仅仅只是隔离多个线程之间的冲突,则使用ThreadLocal

      • 包装线程不安全的集合

        • 可以使用Collections提供的静态方法把这些集合包装成线程安全的集合。

          1. <T> Collection<T> synchronizedCollections(Collection<T> c):返回指定collection对应的线程安全的collection

          2. static <T> List<T> synchronizedList(List<T> list)

          3. static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

          4. static <T> Set<T> synchronizedSet(Set<T> s)

          5. static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)

          6. static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

        • 如果需要把某个集合包装成线程安全的集合,则应该在创建之后立即包装

          HashMap m=Collections.synchronizedMap(new HashMap());

      • 线程安全的集合类

        • java.util.concurrent

        • 支持高效并发访问的集合接口和实现类

          1. Concurrent开头的集合类:支持并发访问的集合

          2. CopyOnWrite开头的集合类:适合读取操作远远大于写入操作的场景,如缓存等

  • 相关阅读:
    Python-手动安装第三方包
    SQL SERVER-根据jobID查job
    python-包模块等概念
    锁表
    Python-try异常捕获
    胶水语言
    C++之多态性与虚函数
    android
    开源许可协议
    hal
  • 原文地址:https://www.cnblogs.com/hust_wsh/p/5095858.html
Copyright © 2020-2023  润新知