一文带你了解J.U.C的FutureTask、Fork/Join框架和BlockingQueue

本文共享自华为云社区《【高并发】J.U.C组件扩展》,作者: 冰 河 。

FutureTask

FutureTask是J.U.C(java.util.concurrent)下的,但不是AQS(AJavabstractQueuedSynchron链表数据结构izer)的子类。其对线程成果的处安全教育手java是什么意思抄报理值得借鉴和在项目中运用。

Thread和Runnajava编译器ble履行完使命无法获取履行成果。Java1.5开端供给链表逆置了Callable和Futu数组的定义re,经链表反转过它们能够在使命履行完毕之后,得到使命履行的成果。

Callable与Runnable接口对比

Callable:泛型接口,供给一个call()办法,支持抛出反常java培训,而且履行后有回来值

Runjava面试题nable:接口,供给一个run()办法,不支持抛出反常,履行后无回来值

Future接口

关于具体的Callable和Runnable使命,能够进行撤销,查询使命是否被撤销,查询是否完结以及获初始化游戏启动器失败取成果等。

Future能够监视方针线程调用call()的状况,当调用Future的get()办法时,就能java是什么意思够取得成果。此刻,履行使命的线程可能不会直接完结,当时线程就开端阻安全教育渠道塞,直到call()办法结束回来成果,当时线程java言语java编译器才会继数组排序续履行。总归,Future能够得到别的线程使命办法的返安全教育渠道回值。

FutureTask类

完成的接口为RunnableFuture,而RunnableFutu初始化是什么意思re接口继承了Runnable和Future两个接口,所以Fut数组词ureTa链表c语言sk类终究也是履行Callable初始化电脑类型的使命。假如FutureTask类的构造办法参数是Runnable的话,会转换成Callable类型。

FutureT安全形式ask类完成了两个接口:链表c言语Runnable和Future。所以,它安全出产法即能够作为Runnable被线程履行,又能够作为初始化电脑时出现问题未进行更改Future得到Callable的回来值,这样设计的初始化失败是怎么解决好处如下:

假设有一个很费时的逻辑,需求核算而且回来这个值,一起,这个值又不是立刻需求,则能够运用Runna初始化是什么意思ble和Future的组合,用另外一个线程去核算回来值,而当时java面试题线程在运用这个回安全工程师来值之前,可安全教育手抄报以做其初始化磁盘他的操作,等到需求这个回来值时,再经过Future得到。

Future示例代码如下:

package io.binghe.concurrency.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@Slf4j
public class FutureExample {
static class MyCallable implements Callable<String>{
@Override
public String call() throws Exception {
log.info("do something in callable");
Thread.sleep(5000);
return "Done";
}
}
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new MyCallable());
log.info("do something in main");
Thread.sleep(1000);
String result = future.get();
log.info("result: {}", result);
executorService.shutdown();
}
}

FutureTask示例代码如下:

package io.binghe.concurrency.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@Slf4j
public class FutureTaskExample {
public static void main(String[] args) throws Exception{
FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
log.info("do something in callable");
Thread.sleep(5000);
return "Done";
}
});
new Thread(futureTask).start();
log.info("do something in main");
Thread.sleep(1000);
String result = futureTask.get();
log.info("result: {}", result);
}
}

Fork/Join结构

坐落J.U.C(java.util.concurrent)中,是Java7初始化电脑时出现问题数组公式化英文中供给的用于履行并行初始化电脑的后果使命的结构,其能够将大使命分割成若干个小使命,终安全教育日究汇总每个小链表逆置使命的成果后得到安全教育平台登录入口终究成果。基本思想和Hadoop的MapRe安全出产法duce思想相似。

主要采用的是作业盗取算法(某个线程从其他行列里链表结构盗取使命来履行),并行分治核算中的一种Work-stealing策略

为什么需求运用作业盗取算法呢?

假如咱们需求做一个比较大的使命,咱们能够把这个使链表结构命分割为若干互不依赖的子使命,为了削减线程间的竞java环境变量配置争,所以把这些子使命别离放到不数组的界说同的行列里,并初始化为每个行列数组词创立一个单独的线程来履java语言行行列里的使命,线程和行列一一对应,比方链表数据结构A线程担任处理A行列里的使命。但是有的线程安全工程师会先把自java模拟器己行列里的使命干完,而其他线程对应的行列里还有使命等候处理。干完活的线程与其等着,不如去javajava培训模拟器帮其初始化电脑他线程干活,所以它就去其他线程的行列数组排序里盗取一个使命来履行。而在这时它们会访问同一个行列,所以链表回转为了削减盗取使命线程和被盗取使命线程之间的竞赛,通初始化电脑的后果常会运用双端初始化电脑的后果行列,被盗取使命线程永远从双端行列数组和链表的差异的头部拿使命履行,而盗取初始化游戏启动器失利使命的线程永远从双端行列的尾部拿使命履行。

作业安全教育手抄报盗取算法的长处:

充分利用线程进行并行核算,并削减了线程间的竞赛

作业盗取算法的缺点:

在某些状java面试题况下仍是存在竞赛,比方双端行列里只有一个使命时。而且该算法会耗费更多的系统资源,比方安全教育日创立多个线程和多个双端行列。数组和链表的差异链表c语言

关于Fork/Join结构而言链表结构,当一个使命正在等候它运用安全教育平台登录J安全oin链表逆置操作创立的子使命结束时,履行这个使命的作业线程查找其他未被履行的链表逆置使命,并开端履行这些未被初始化sdk什么意思履行的使命,经过这种办法,线程充分利用它们的运转时刻来进步应用程序的性能。为了完成这个方针,Fork/Join结构履行的任初始化失利是怎样解决务有一些局限性。

Fork/Join结构局限性:

(1)使命只能运用F链表和数安全生产法组的差异ork和Join操作来进行同步机安全教育手抄报制,假如运用了其他同步机数组排序制,则在同步操作时,作业线程就不能履行其他使命了。比方,在Fork/Join安全模式结构中,使使命进行了安全教育渠道登录进口睡眠,那么,在睡眠期间内,正在履行这个使命的作业线程将不会履行其他使命了。

(2)在数组Fork/Join结构中,所拆分的使命数组去重不应该去履行IO操作,比方:读写数数组的界说据文件

(3)使命不能抛出查看链表的特点反常,必须经过必要的代码来出来这些反常

Fork/Join结构的中心类

Fork/Join安全教育日结构的中心是数组词两个类:ForkJoinPool和ForkJoinTask。ForkJoinPool担任完成作业盗取算法、管理作业线程、供给关于链表结构数组去重办法数组去重办法的状态以及履行信息。ForkJoinTask主javaee要供给在使命中履行Fork和Join操作的机制。

示例代码如下:

package io.binghe.concurrency.example.aqs;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveTask;
@Slf4j
public class ForkJoinTaskExample extends RecursiveTask<Integer> {
public static final int threshold = 2;
private int start;
private int end;
public ForkJoinTaskExample(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
//假如使命满足小就核算使命
boolean canCompute = (end - start) <= threshold;
if (canCompute) {
for (int i = start; i <= end; i++) {
sum += i;
}
} else {
// 假如使命大于阈值,就分裂成两个子使命核算
int middle = (start + end) / 2;
ForkJoinTaskExample leftTask = new ForkJoinTaskExample(start, middle);
ForkJoinTaskExample rightTask = new ForkJoinTaskExample(middle + 1, end);
// 履行子使命
leftTask.fork();
rightTask.fork();
// 等候使命履行结束兼并其成果
int leftResult = leftTask.join();
int rightResult = rightTask.join();
// 兼并子使命
sum = leftResult + rightResult;
}
return sum;
}
public static void main(String[] args) {
ForkJoinPool forkjoinPool = new ForkJoinPool();
//生成一个核算使命,核算1+2+3+4
ForkJoinTaskExample task = new ForkJoinTaskExample(1, 100);
//履行一个使命
Future<Integer> result = forkjoinPool.submit(task);
try {
log.info("result:{}", result.get());
} catch (Exception e) {
log.error("exception", e);
}
}
}

BlockingQueue

堵塞行列,是线程安全的。

被堵塞的状况如下:

(1)当数组去重办法行列java编译器满时,进行入初始化磁盘行列操作

(2)当行列空时,进安全教育平台行出行列操作

运用场景如下:

主要在出产者和消费者场景

Bl安全教育渠道登录ockingQueue的办法

BlockingQueue 具有 4 组不同的办法用于刺进、移除以及对行列中的元素进行查看。假如恳求的操作不能得到当即java安全教育平台作业登录怎样读履行的话,每个办法的表现也不同。这些办法如下:

一文带你了解J.U.C的FutureTask、Fork/Join结构和BlockingQueue

四组不同的行为办法解释:

  • 抛出反常

假如企图的操作无法当即履行,抛一个反常。

  • 特殊值

假如企安全教育平台登录图的操作无法当即履行,回来一个特定的值(常常是 true / false)。

  • 堵塞

假如企图的操作无法当即履行,该办法调用将会产生堵塞,直到能够履行。

  • 超时

假如企图的操作无法当即初始化sdk什么意思履行,该安全教育渠道登录进口办法调用将会产生堵塞,直到能够履行,但等候数组的界说时刻不会超过给定值。初始化回来一个特定值以奉告该操作是否成功(典数组去重方法型的是 true / false)。

BlockingQueue的完成类如下:

  • ArrayBlockingQuejava是什么意思ue:有界的堵塞行列(容量有限,必须在初始化的时分指定容量巨细,容量巨细指定后就不能java语言再变化)链表排序,内部完成是一个数组,以FIFO的办法存储数据初始化游戏启动器失利安全教育渠道登录进口最新刺进的目标是尾部,最新移除的目标是头部。
  • DelayQu初始化游戏启动器失利eue:堵塞的是内部元素,DelayQueue中的元素必须完成一个初始化sdk什么意思接口——Delayed(存在于J.U.C下)。Delayed接口继承了Comparable接口,这是因为Delayed接口中的元素需求进行排序,一般状况下,都是按照Delayed接口中的元素过期时刻的优先级进行排序。应用场景主要有:定时封闭衔接、缓存目标、超时处理等。内部完成运用Prjava怎样读iorit链表的特点yQueue和ReentrantLock。
  • LinkedBlock链表数据结构ingQueue:巨细配置是可选的,假如初始化时指定了巨细,则是有鸿沟的;假如初始化时未指定巨细初始化电脑,则是无鸿沟的初始化游戏启动器失败(其实默链表反转认巨细是Integer类型的最大值)。内部完成时一个链表,以FIFO的办法存储数据,最新java训练刺进javascript的目标java训练是尾部,最新移除的目标是头部。
  • PriorityBlockingQueu初始化电脑时出现问题e:带优先级的堵塞队链表回转列,无鸿沟,但是有排序规矩,答应刺进空对链表的特色象(也便是null)。所有刺数组和链表的区别进的目标必须完成Comparabl链表回转e接初始化电脑口,行列优先级的排序规矩便是按照对Comparable接口的完成来界说的。能够从PriorityBlockingQ数组的界说ueue中取初始化是什么意思得一个迭代器Iterator,但这个迭代器并不保证按照优先级的顺序进链表结构行迭代。
  • Sy安全教育平台nchr链表onousQueue:行列内部仅答应容纳一个元素,当一个线程刺进一个元素初始化磁盘后,就会被堵塞,安全出产法安全模式非这个元素被另一个线程消费。因此,也称SynchronousQueue为同步行列。SynchronousQueue是一个无界非缓存的行列。准确的说,它不存储元素,放入元素只有等候安全教育平台登录入口取走元素之后java言语,才干再次放入元素

点击重视安全教育平台,榜首时初始化sdk什么意思间了解华为云新鲜技术~

发表评论

提供最优质的资源集合

立即查看 了解详情