java 并行_Java 并行编程!

多核处理器现在已广泛应用于服务器、台式机和便携机硬件。它们还扩展到到更小的设备,如智能电话和平板电脑。由于进程的线程可以在多个内核上并行执行,因此多核处理器为并发编程打开了一扇扇新的大门。为实现应用程序的最大性能,一项重要的技术就是将密集型任务拆分成可以并行执行的若干小块,以便最大程度利用计算能力。

传统上,处理并发(并行)编程一直很困难,因为您不得不处理线程同步和共享数据的问题。Groovy (GPar)、Scala 和 Clojure 社区的努力已经证明,人们对 Java 平台上并发编程的语言级支持的兴趣十分强烈。这些社区都尝试提供全面的编程模型和高效的实现,以屏蔽与多线程和分布式应用程序相关的难点。但不应认为 Java 语言本身在这方面逊色。Java Platform, Standard Edition (Java SE) 5 及后来的 Java SE 6 引入了一组程序包,可以提供强大的并发构建块。Java SE 7 通过添加并行支持进一步增强了这些构建块。

下文首先简单回顾了 Java 并发编程,从早期版本以来已经存在的低级机制开始。然后在介绍 Java SE 7 中由分解/合并框架提供的新增基本功能分解/合并任务之前,先介绍 java.util.concurrent 程序包添加的丰富基元。文中给出了这些新 API 的示例用法。最后,在结束之前对方法进行了讨论。

下面,我们假定读者拥有 Java SE 5 或 Java SE 6 编程背景。在此过程中,我们还将介绍 Java SE 7 一些实用的语言发展。

Java 并发编程

传统线程

过去,Java 并发编程包括通过 java.lang.Thread 类和 java.lang.Runnable 接口编写线程,然后确保其代码以正确、一致的方式对共享可变对象进行操作并避免错误的读/写操作,同时不会产生由于锁争用条件所导致的死锁。以下是基本线程操作的示例:

Thread thread = new Thread() {

@Override public void run() {

System.out.println(">>> I am running in a separate thread!");

}

};

thread.start();

thread.join();

本示例中的代码所做的只是创建一个线程,该线程将一个字符串打印到标准输出流。主线程通过调用 join() 等待所创建的(子)线程完成。

这样直接操作线程对于简单示例来说是不错,但对于并发编程,这种代码很快就容易产生错误,尤其是当多个线程需要合作执行一个大型任务时。在这样的情况下,需要协调其控制流。

例如,某个线程执行的完成可能依赖于其他线程执行完成。通常人们熟知的示例是生产者/使用者的例子,如果使用者的队列已满则生产者应等待使用者,当队列为空时使用者应等待生产者。这一要求可通过共享状态和条件队列得到满足,但您仍需要通过对共享状态对象使用java.lang.Object.notify() 和 java.lang.Object.wait() 来使用同步,这很容易出错。

最后,一个常见的问题是对大段代码甚至是整个方法使用同步和提供互斥。尽管此方法可产生线程安全的代码,但由于排除实际上过长所引起的有限并行度,该方法通常导致性能变差。

正如计算中经常发生的那样,操作低级基元以实现复杂操作会打开错误之门,因此开发人员应想办法将复杂性封装在高效的高级库中。Java SE 5 正好为我们提供了这种能力。

java.util.concurrent 程序包的丰富基元

Java SE 5 引入了一个名为 java.util.concurrent 的程序包系列,Java SE 6 对其进行了进一步的增强。该程序包系列提供了以下并发编程基元、集合和特性:

执行器是对传统线程的增强,因为它们是从线程池管理抽象而来的。它们执行与传递到线程的任务类似的任务(实际上,可封装实现java.lang.Runnable 的实例)。有些实现提供了线程池和调度策略。而且,可以通过同步和异步方式获取执行结果。

线程安全队列允许在并发任务之间传递数据。底层数据结构和并发行为有着丰富的实现,底层数据结构的实现包括数组列表、链接列表或双端队列等,并发行为的实现包括阻塞、支持优先级或延迟等。

细粒度的超时延迟规范,因为 java.util.concurrent 程序包中的大部分类均支持超时延迟。例如,如果任务在规定时间范围内无法完成,执行器将中断任务执行。

丰富的同步模式,不仅仅是 Java 中低级同步块所提供的互斥。这些模式包括信号或同步障碍等常用语法。

高效、并发的数据集合(映射、列表和集),通过使用写时复制和细粒度锁通常可在多线程上下文中产生出色的性能。

原子变量,可以使开发人员免于亲自执行同步访问。这些变量封装了常用的基元类型,如整型或布尔值,以及对其他对象的引用。

超出固有锁所提供的锁定/通知功能范围的多种锁,例如,支持重新进入、读/写锁定、超时或基于轮询的锁定尝试。

例如,考虑以下程序:

注意:由于 Java SE 7 引入的新的整数文本,可以在任意位置插入下划线以提高可读性(例如,1_000_000)。

import java.util.*;

import java.util.concurrent.*;

import static java.util.Arrays.asList;

public class Sums {

static class Sum implements Callable {

private final long from;

private final long to;

Sum(long from, long to) {

this.from = from;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值