Java多线程与并发编程——ConditionCallable&Future
Posted 守夜人爱吃兔子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程与并发编程——ConditionCallable&Future相关的知识,希望对你有一定的参考价值。
前言
每天积累一点点,积跬步至千里。今天学习
JUC
包中的Condition、Callable&Future。
Condition等待与唤醒
JUC
提供了这么多的工具类,目的是让我们对于程序中多线程环境下,对线程的控制,Conditon
对象,用来让指定的线程等待与唤醒,按照我们预期的顺序执行,大白话就是,我们完全掌控线程的执行顺序。注意: 它必须和ReentrantLock
重入锁配合使用。Condition
用于替代wait()/notify()
方法
notify
只能随机唤醒等待的线程,而Condition
可以唤醒指定线程,这有利于更好的控制并发程序。
Condition核心方法
await()
阻塞当前线程,直到signal()唤醒signal()
唤醒被await()
的线程,从中断处继续执行signalAll()
唤醒所有被await()
阻塞的线程
代码示例
- 创建三个线程,分别打印
1
、2
、3
,为了效果明显加了1000ms
睡眠,正常情况下按顺序打印肯定是1
、2
、3
- 但是现在我们想要打印
3
、1
、2
,这时就可以利用Condition
来实现控制,看下面代码
public class ConditionSample {
public static void main(String[] args) throws InterruptedException {
ReentrantLock lock = new ReentrantLock();
Condition c1 = lock.newCondition();
Condition c2 = lock.newCondition();
new Thread(() -> {
lock.lock();
try {
c1.await();//阻塞当前线程
Thread.sleep(1000);
System.out.println(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
new Thread(() -> {
lock.lock();
try {
c2.await();//阻塞当前线程
Thread.sleep(1000);
System.out.println(2);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
new Thread(() -> {
lock.lock();
try {
Thread.sleep(1000);
System.out.println(3);
c1.signal();
c2.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}).start();
}
}
我们通过
ReentrantLock
对象创建了2
个Condition
对象c1
、c2
.相当于两个标记锁,分别加在打印1
和2
的线程上,等3
打印完成,再去控制先唤醒哪个,先唤醒哪个则哪个打印输出,实现预期效果。
Callable&Future
- Callable和Runnable一样用来创建线程,区别在于Callable有返回值并且可以抛出异常
- Future是一个接口。它用于表示异步计算的结果。提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。
代码示例
获取
10000
以内所有的质数,单线程循环查找的做法这里就不做介绍了,看下面示例代码,我们可以通过多线程的方式去判断是否为质数,然后将结果接收返回。这里获取质数的方法比较简单,如果换成更为复杂的逻辑,多线程的效率优势就会很明显了。
public class FutureSample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 2; i <= 10000; i++) {
Computor c = new Computor();
c.setNum(i);
Future<Boolean> result = executorService.submit(c);
try {
Boolean r = result.get();
if (r) {
System.out.println(c.getNum());
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executorService.shutdown();
}
}
class Computor implements Callable<Boolean> {
private Integer num;
public Integer getNum() {
return num;
}
public void setNum(Integer num) {
this.num = num;
}
@Override
public Boolean call() throws Exception {
boolean isprime = true;
for (int i = 2; i < num; i++) {
if (num % i == 0) {
isprime = false;
break;
}
}
return isprime;
}
}
Future
是对用于计算的线程进行监听,因为计算是在其他线程中执行的,所以这个返回结果的过程是异步的executorService.submit(c);
将c
对象提交给线程池,如有空闲线程立即执行里面的call
方法result.get();
用于获取返回值,如果线程内部的call
没有执行完成,则进入等待状态,直到计算完成
以上是关于Java多线程与并发编程——ConditionCallable&Future的主要内容,如果未能解决你的问题,请参考以下文章
Java多线程系列:线程的五大状态,以及线程之间的通信与协作