• 《Java核心技术(卷1)》笔记:第12章 并发


    线程

    1. (P 552)多进程多线程的本质区别:每一个进程都拥有自己的一整套变量,而线程共享数据

    2. (P 555)线程具有6种状态

      • New(新建):使用new操作符创建线程时
      • Runnable(可运行):调用start方法
      • Blocked(阻塞)
      • Waiting(等待)
      • Timed waiting(计时等待)
      • Terminated(终止):run方法正常退出、没有捕获异常
      image-20200630154201750
    3. (P 558)interrupt方法用来请求终止一个线程。当对一个线程调用interrupt方法时,就会设置线程的中断状态。每个线程都应该不时地检查这个标志,以判断线程是否被中断

    4. (P 559)如果线程被阻塞,就无法检查中断状态,因此引入InterruptedException异常。当在一个被sleepwait调用阻塞的线程上调用interrupt方法时,那个阻塞调用将被一个InterrupedtException异常中断

    5. (P 559)如果设置了中断状态,此时倘若调用sleep方法,它不会休眠。实际上,它会清除中断状态并抛出InterruptedException。因此,如果循环里调用了sleep,不要检测中断状态,而应当捕获InterruptedException异常

    6. (P 560)interruptedisInterrupted以及interrupt方法的区别:

      方法 性质 作用 影响
      interrupted Thread的静态方法 检查当前线程是否被中断 会清除该线程的中断状态
      isInterrupted Thread的实例方法 测试线程是否被中断 不会改变中断状态
      interrupt Thread的实例方法 向线程发送中断请求 会设置线程的中断状态
    7. (P 561)守护线程:唯一用途是为其他线程提供服务,当只剩下守护线程时,虚拟机就会退出。可通过setDaemon方法将线程设为守护线程

    8. (P 561)线程的run方法不能抛出任何检查型异常,在线程死亡之前,异常会传递到一个用于处理未捕获异常的处理器(必须实现Thread.UncaughtExceptionHandler接口)

      方法 性质 作用
      setUncaughtExceptionHandler Thread的实例方法 为任何线程安装一个处理器
      setDefaultUncaughtExceptionHandler Thread的静态方法 为所有线程安装一个默认的处理器

    同步

    1. (P 568)Java提供的两种可防止并发访问代码块的机制:

      • synchronized关键字

      • ReentrantLock类(重入锁)

        myLock.lock();	// 一个ReentrantLock对象
        try {
            ...
        } finally {
            myLock.unlock();	// 必须放在finally里,不能使用try-with-resources
        }
        
    2. (P 570)重入(reentrant)锁:线程可以反复获得已拥有的锁,被一个锁保护的代码可以调用另一个使用相同锁的方法。注意确保临界区中的代码不要因为抛出异常而跳出临界区

    3. (P 572)一个锁对象可以有一个或多个相关联的条件对象,可以使用newCondition方法获得一个条件对象。

      方法 性质 作用
      newCondition ReentrantLock的实例方法 获得一个条件对象
      await Condition的实例方法 当前线程现在暂停,并放弃锁
      signalAll Condition的实例方法 解除等待这个条件的所有线程的阻塞状态
      signal Condition的实例方法 随机选择一个线程解除其阻塞状态

      使用形式:

      class A {
          private var lock = new ReentrantLock();
          private Condition condition;
          ...
          
          private A() {
              ...
              condition = lock.newCondition();
          }
          
          private someMethod() {
              lock.lock();
              try {
                  ...
                  while(!(OK to proceed)) {	// await调用通常放在循环中
                      condition.await();
                  }
                  ...
                  condition.signalAll();	// signalAll只是通知等待的线程:现在有可能满足条件,值得再次检查条件
                  						// 只要一个对象的状态有变化,而且可能有利于等待的线程,就可以调用signalAll
                  						// signalAll只是解除等待线程的阻塞,使这些线程可以在当前线程释放锁之后竞争访问对象
              } finally {
                  lock.unlock();
              }
          }
          
          ...
      }
      
    4. (P 576)Java中的每个对象都有一个内部锁只有一个关联条件)。如果一个方法声明时有synchronized关键字,那么对象的锁将保护整个方法

      方法 性质 作用 等价于
      wait Object的实例方法 将一个线程增加到等待集中 await
      notify/notifyAll Object的实例方法 解除等待线程的阻塞 signal/signalAll
    5. (P 577)将静态方法声明为同步也是合法的,如果调用这样一个方法,它会获得相关类对象(Class对象)的内部锁

    6. (P 577)内部锁和条件存在一些限制

      • 不能中断一个正在尝试获得锁的线程
      • 不能指定尝试获得锁时的超时时间
      • 每个锁仅有一个条件可能是不够的
    7. (P 579)同步块:

      synchronized(obj) {	// 会获得obj对象的锁
          ...
      }
      
    8. (P 580)监视器的特性:

      • 监视器是只包含私有字段的类
      • 监视器类的每个对象有一个关联的
      • 所有方法有这个锁锁定
      • 锁可以有任意多个相关联的条件
    9. (P 581)volatile关键字为实例字段的同步访问提供了一种免锁机制,volatile变量不能提供原子性

      • 另一种安全访问共享字段的情况:将字段声明为final
    10. (P 582)java.util.concurrent.atomic包中有很多类使用了很高效的机器级指令来保证其他操作的原子性

    11. (P 586)线程局部变量:ThreadLocal

      public static final ThreadLocal<SimpleDateFormat> dataFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));
      // 在一个给定线程中首次调用get时,会调用构造器中的lambda表达式
      // 在此之后,get方法会返回属于当前线程的那个实例
      String dateStamp = dataFormat.get().format(new Date());
      

    线程安全的集合

    1. (P 589)阻塞队列(blocking queue):addelementofferpeekpollputremovetake

    2. (P 595)高效的映射、集和队列:java.util.concurrent包提供了ConcurrentHashMapConcurrentSkipListMapConcurrentSkipListSetConcurrentLinkedQueue

    3. (P 602)同步包装器(synchronization wrapper):任何集合类都可以通过使用同步包装器变成线程安全的

      List<E> synchArrayList = Collections.synchronizedList(new ArrayList<E>());
      Map<K, V> synchHashMap = Collections.synchronizedMap(new HashMap<K, V>());
      

    线程池

    1. (P 603)CallableRunnable类似,但是有返回值,只有一个call方法

    2. (P 604)Future保存异步计算的结果

    3. (P 604)执行Callable的一种方法是使用FutureTask,它实现了FutureRunnable接口

      Callable<Integer> task = ...;
      var futureTask = new FutureTask<Integer>(task);
      var t = new Thread(futureTask);		// it's a Runnable
      t.start();
      ...
      Integer result = futureTask.get();	// it's a Future
      
    4. (P 605)执行器(Executors)类有许多静态工厂方法,用来构造线程池

    5. (P 606)使用线程池时所做的工作:

      1. 调用Executors类的静态方法newCachedThreadPoolnewFixedThreadPool
      2. 调用submit提交RunnableCallable对象
      3. 保存好返回的Future对象,以便得到结果或者取消任务
      4. 当不想再提交任何任务时,调用shutdown
    6. (P 607)控制任务组

      方法 性质 作用 备注
      invokeAny ExecutorService的实例方法 提交一个Callable对象集合中的所有对象,并返回某个已完成任务的结果
      invokeAll ExecutorService的实例方法 提交一个Callable对象集合中的所有对象,并返回表示所有任务答案的一个Future对象列表 这个方法会阻塞,直到所有任务都完成
    7. (P 612)fork-join框架:专门用来支持计算密集型任务,假设有一个处理任务,它可以很自然地分解为子任务

    异步计算

    1. (P 615)CompletableFuture类实现了Future接口,它提供了获得结果的另一种机制。你要注册一个回调,一旦结果可用,就会(在某个线程中)利用该结果调用这个回调(与之不同的是,Future中的get方法会阻塞)
    2. (P 615)Supplier<T>Callable<T>:都描述了无参数而且返回值类型为T的函数,不过Supplier函数不能抛出检查型异常

    进程

    1. (P 628)Process类在一个单独的操作系统进程中执行一个命令,允许我们与标准输入、输出和错误流交互。ProcessBuilder类则允许我们配置Process对象
    2. (P 631)ProcessHandle接口:要获得程序启动的一个进程的更多信息,或者想更多地了解你的计算机上正在运行的任何其他进程,可以使用ProcessHandle接口
    3. (P 631)得到ProcessHandle的4种方式:
      • 给定一个Process对象pp.toHandle()会生成它的ProcessHandle
      • 给定一个long类型的操作系统进程IDProcessHandle.of(id)可以生成这个进程的句柄
      • Process.current()是运行这个java虚拟机的进程句柄
      • ProcessHandle.allProcesses()可以生成对当前进程可见的所有操作系统进程的Stream<ProcessHandle>
  • 相关阅读:
    WinForm DotNetBar 动态添加DataGridView
    调用Excel宏批量处理文件
    jquery datatables+MVC+WCF
    DataTables warning : Requested unknown parameter '0' from the data source for row 0错误
    数据库中判断内容中是否包含中文
    TerraGate SFS Manager配置时权限设置问题
    AutoCAD开发5--批量修改dwg文件
    关闭浏览器时提示的javascript事件
    ArcGIS for JS 离线部署
    [转]ArcGIS for Silverlight:关于尝试连接到REST端点时发生安全异常的解决方案
  • 原文地址:https://www.cnblogs.com/qinjinyu/p/13461696.html
Copyright © 2020-2023  润新知