Java8中的简易并发

我们在《实战Java高并发程序设计》一书中,专门介绍过java 8中对并发的改进。这里我通过转载一篇博客来说简单介绍下。


有人曾经说过(很抱歉,我们找不到原句了):

初级程序员认为并发很难。
中级程序员认为并发很简单。
高级程序员认为并发很难。

这说的很对。但是从好的方面来看,Java8为我们带来了转机,通过lambda表达式和改进的API可以使得编写并发代码更容易。让我们来具体的看看Java8的改进吧:

Java8对JDK 1.0 API的改进

java.lang.Thread早在JDK 1.0版本中就已经存在。在java8中被注解为功能性接口java.lang.Runnable也是。

从现在起,几乎不需要动大脑我们就可以提交Runnables给一个线程。让我们假设我们有一个很耗时的操作:

1
2
3
4
5
6
7
public static int longOperation() {
     System.out.println( "Running on thread #"
     + Thread.currentThread().getId());
 
     // [...]
     return 42 ;
}

我们可以用多种方法把这个操作传递给线程,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Thread[] threads = {
  
     // Pass a lambda to a thread
     new Thread(() -> {
     longOperation();
     }),
  
     // Pass a method reference to a thread
     new Thread(ThreadGoodies::longOperation)
};
  
// Start all threads
Arrays.stream(threads).forEach(Thread::start);
  
// Join all threads
Arrays.stream(threads).forEach(t -> {
     try { t.join(); }
     catch (InterruptedException ignore) {}
});

就像我们在之前的博文里提到的一样,lambda表达式没有一个简洁的方式来处理被检查异常实在是一大憾事。在java.util.function包中新增的功能性接口都不会抛出被检查异常,把这项工作留给了调用端。

在上一篇博文中,我们已经因此而发布了jOOλ(also jOOL,jOO-Lambda)包,该包包装了JDK中的每一个功能性接口,具有相同功能而且也允许抛出被检异常。这在使用老的JDK API时特别有用,例如JDBC,或者上面提到的Thread API。使用jOOλ,我们可以这么写:

1
2
3
4
// Join all threads
Arrays.stream(threads).forEach(Unchecked.consumer(
     t -> t.join()
));

Java8中改进的Java5 API

Java的多线程功能一直没有什么起色,直到Java5的ExecutorService的发布。管理多线程是一个负担,人们需要额外的库或者一个J2EE/JEE容器来管理线程池。这些用Java5来处理已经容易了很多。我们现在可以提交一个Runnable对象或者一个Callable对象到ExcutorService,它管理自己的线程池。

下面是一个我们如何在Java8中利用这些Java5的并发API的例子:

1
2
3
4
5
6
7
8
9
10
11
ExecutorService service = Executors
     .newFixedThreadPool( 5 );
  
Future[] answers = {
     service.submit(() -> longOperation()),
     service.submit(ThreadGoodies::longOperation)
};
  
Arrays.stream(answers).forEach(Unchecked.consumer(
     f -> System.out.println(f.get())
));

注意看,我们是如何再次使用jOOλ中的UncheckedConsumer来包装在运行期调用get()方法抛出的被检异常。

Java8中的并行和ForkJoinPool

现在,Java8的Streams API在并发和并行方面有了很大改进。
在Java8中你可以写出如下的代码:

1
2
3
4
Arrays.stream( new int []{ 1 , 2 , 3 , 4 , 5 , 6 })
   .parallel()
   .max()
   .ifPresent(System.out::println);

虽然在这个特殊的例子中不是很必要,但还是挺有意思的,你仅仅调用了parallel()就运行IntStream.max()来启用ForkJoinPool,而你不必担心包含的ForkJoinTasks。这是非常有用的,因为不是每个人都能够接受JDK7中引进的复杂的JorkJoin API

原文链接:  jaxenter  翻译:  ImportNew.com  kingviker
译文链接:  http://www.importnew.com/11590.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值