java并发实现_Java并发实现

Thread

原生线程并发难度在于理解力和想像力。new Thread(()->{

//to do

}).start();

Executors

Java并发领军人物Doug Lea杰作,Executors拥有众多应用解决方案。

1、固定数量的线程池:Executors.newFixedThreadPool(10);

没有空闲线程,新任务加入时,任务会被放入队列,直到有可用线程。

2、根据需要自动扩充线程数,并能重用已构造的线程。Executors.newCachedThreadPool();

对执行短暂异步任务的场景能明显提高性能。

调用execute时,有空闲线程则重用,没有则创建。空闲60秒从缓存中清除。

3、可指定延迟执行时间或定时周期Executors.newScheduledThreadPool(10);

4、单线程,任务被放入队列,执行出现异常,导致线程不能正常返回时,则创建新线程。Executors.newSingleThreadExecutor();

5、工作窃取线程池,线程间相互协作,共同完成任务,每个线程领取的任务数不固定。Executors.newWorkStealingPool();

ForkJoinPool

使用时需告诉ForkJoinPool如何分解任务。

如:有0~1000的数字,若让每个线程领到10个数字,需在线程拿到数字开始与结束区间时做出判断,看区间是否大于10,大于10则需再次分解。

线程调度场景中ForkJoinPool有专门的抽象类定义,只需重写任务分解逻辑。

ForkJoinTask有多个子类,子类负责分解逻辑。

针对不同场景选择不同子类,定义分解逻辑。//Jdk7 api,后续版本允许方法有返回值

protected void compute() {

if(et - st < unit){ //判断区间是否大于规定值

c.call(st, et); //达到理想分解度,调用业务处理逻辑

}else {

int middle =(st+et)/2; //对任务进行分解

TaskUnit l = new TaskUnit(st, middle,c); //将任务一分为二,变成两个任务

TaskUnit r = new TaskUnit(middle, et,c);

l.fork(); //将任务交由线程调度去执行

r.fork();

l.join();

r.join();

}

}

}

示例采用递归方式分解任务,实现RecursiveAction规范。ForkJoinPool完整示例。

Actor编程模型

Actor模型由Carl Hewitt在几十年前提出,网络中高性能并行处理方案 - 当时还没有这种环境。

如今,硬件和基础设施能力已经赶上,传统面向对象编程(OOP)模型,无法完全构建具有苛刻要求的分布式系统。

OOP核心是封装,规定对象内部数据,不能直接从外部访问,只能通过调用一组特定方法访问或修改,保护封装数据的不变性及安全。

消息传递避免了锁定和阻塞,actor不是方法间的调用,而是互相发送消息。

发送消息不会导致调用方与被调用方处在同一个线程中。

Actor可以连续发送而不会阻塞。因此,可以在单位时间内完成更多操作。

对象在方法返回时,释放对执行线程的控制。

在这方面,actor的行为与对象非常相似,它们在处理完消息时,对消息作出反应并返回执行。

通过这种方式,actor实现了如我们所想的对象调用。

传递消息和调用方法间的区别是:

消息没有返回值,通过消息,actor将工作委托给另一个actor。

正如在调用堆栈时那样,若期望一个返回值,则发送方会被阻塞,或者与被调用的actor处在同一线程上。

相反,actor接收者在回复消息中带着返回结果。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值