《On Java进阶卷》阅读笔记(三)

第5章 并发编程

并发:同时处理多个任务,即不必等待一个任务完成就能开始处理其他任务。并发解决的是阻塞问题,即一个任务必须要等待非其可控的外部条件满足后才能继续执行,最常见的例子是I/O,一个任务必须要等待输入才能执行(即被阻塞),类似的场景称为I/O密集型问题。

并行:同时在多处执行多个任务。并行解决的是所谓的计算密集型问题,即通过把任务分成多个部分,并在多个处理器上执行,从而提升程序运行的速度。

两者的关键都是【同时处理多个任务】,而并行则额外包括了多处理器分布式处理的概念。更重要的是,两者处理不同类型的问题。

并发是一系列聚焦于如何减少等待并提升性能的技术。

多线程并不是在多任务操作系统中fork出来的额外的进程,而是在执行程序所维护的单个进程内部创建多任务。

Java并发四定律:

  1. 不要使用并发。切忌自己手动写并发,尽量使用知名的库。
  2. 一切都不可信,一切都很重要。要保持质疑的态度面对并发,因为在非并发程序里不会有的问题,在并发里可能会有。
  3. 能运行并不代表没有问题。
  4. 终究要理解并发。不能因为你并未手动开启一个线程,就认为你可以避免编写线程代码。要熟悉使用的框架,它内含线程代码。

并行流:

代码里使用了.parallel()

  • 流的并行化将输入的数据拆分成多个片段,这样就可以针对这些独立的数据片段应用各种算法。
  • 数组的切分非常轻量、均匀,并且可以完全掌握切分的大小。
  • 链表则完全没有这些属性,对其切分意味着会将其拆分成第一个元素 和 其他剩余的部分,这没有什么实际用处。
  • 无状态生成器的表现很像数组,以上对range的使用就是无状态的。
  • 迭代式生成器的表现很像链表,iterate()就是一个迭代式生成器

盲目地应用内建parallel操作有时反而能让程序变得特别慢。

单纯对集合调用stream或者parallelStream是没有问题的,然而有时使用并行后再进行collect会导致数据和非并行的不一致。

将parallel方法和limit方法一起配合使用,可以告诉程序预先选取一组值,以作为流输出。

peek()方法:它会从流中拉取出一个值来进行想要的操作,但并不会影响在流中传递下去的元素。

创建和运行任务:

Java5新增了一些线程池。

ExecutorService exec = Executors.newSignleThreadExcutor();

exec.shutdown();

exec.shutdown会告诉ExecutorService完成所有已提交的任务,但不再接收任何新任务。

多个任务同时修改同一个变量会导致所谓的竞态条件。

使用Callable类代替Runnable类,优势是方法有返回值。

线程池执行实现Callable类的线程方法是exec.invokeAll

只有当所有任务都完成时,invokeAll才会返回由Future组成的List,每个Future都对应一个任务。

得到Future的返回结果是需要阻塞的,并不是一个有效的解决办法。可以用CompletableFuture代替

CompletableFuture<Object> cf = CompletableFuture.completedFuture(new Object());
Object obj = cf.get();

可以使用thenApply将任务串联起来,一个执行完执行下一个。

死锁:

谁都动不了,这称为死锁。

哲学家用餐问题。

出现死锁需要同时满足的条件:

  1. 互斥。这些任务使用的至少一项资源必须不是共享的。
  2. 至少一个任务必须持有一项资源,并且等待正被另一个任务持有的资源。
  3. 不能从一个任务中抢走一项资源。
  4. 会发生循环等待,其中一个任务等待另一个任务持有的资源,另一个任务又在等待另一个任务持有的资源。

最简单方法是永远不要共享资源。

构造器并不是线程安全的:

将构造器设为同步是没有实际意义,因为这样做会阻塞正在构造的对象。在对象的所有构造器完成工作之前,其他线程通常无法使用该对象。

单例模式。

并行流方案最合适解决无脑并行类型问题,即那种很容易将数据拆分成无差别、易处理的片段来处理的问题。

CompletableFuture处理的工作片段最好是各不相同的,这样效果最好。CompletableFuture看起来更像面向任务的,而不是面向数据。

并发的缺点:

  1. 线程等待资源时会导致系统变慢;
  2. 管理线程需要额外的CPU开销;
  3. 不合理的设计决策会导致不必要的复杂性;
  4. 会带来饥饿、竞争、死锁、活锁等病态现象;
  5. 平台不一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值