Java中实现并发的方法有哪些(java,开发技术)

时间:2024-05-06 09:16:01 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    Java%E4%B8%AD%E5%AE%9E%E7%8E%B0%E5%B9%B6%E5%8F%91%E7%9A%84%E6%96%B9%E6%B3%95%E6%9C%89%E5%93%AA%E4%BA%9B

Java程序默认以单线程方式运行。

Java 用过synchronized 关键字来保证一次只有一个线程在执行代码块。

Volatile 关键字保证任何线程在读取Volatile修饰的变量的时候,读取的都是这个变量的最新数据。

创建thread会有很多overhead,性能低且不易管理

因为Runnable对象无法向调用者返回结果,我们可以用Callable类来返回结果。

CompletableFuture 在Future的基础上增加了异步调用的功能。callback()函数Thread执行结束的时候会自动调用。

CompletableFuture既支持阻塞,也支持非阻塞的callback()

补充:Java如何处理高并发的情况

为了更好的理解并发和同步,需要先明白两个重要的概念:同步和异步

所谓同步,可以理解为在执行完一个函数或方法之后,一直等待系统返回值或消息,这时程序是出于阻塞的,只有接收到返回的值或消息后才往下执行其它的命令。 同步就是一件事,一件事情一件事的做。

异步,执行完函数或方法后,不必阻塞性地等待返回值或消息,只需要向系统委托一个异步过程,那么当系统接收到返回值或消息时,系统会自动触发委托的异步过程,从而完成一个完整的流程。异步就是,做一件事情,不影响做其他事情。

同步关键字synchronized,假如这个同步的监视对象是类的话,那么如果当一个对象 访问类里面的同步方法的话,那么其它的对象如果想要继续访问类里面的这个同步方法的话,就会进入阻塞,只有等前一个对象 执行完该同步方法后当前对象才能够继续执行该方法。这就是同步。相反,如果方法前没有同步关键字修饰的话,那么不同的对象可以在同一时间访问同一个方法,这就是异步。

脏数据:就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据(Dirty Data),依据脏数据所做的操作可能是不正确的。

多个进程或线程同时(在同一段时间内)访问同一资源会产生并发问题。

比如A、B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户减去 50元,A先提交,B后提交。 最后实际账户余额为1000-50=950元,但本该为 1000+100-50=1050。这就是典型的并发问题。如何解决?

处理并发和同同步问题主要是通过锁机制。

一种是java中的同步锁,典型的就是同步关键字synchronized。

另外一种比较典型的就是悲观锁和乐观锁。

1)使用同步关键字synchronized

2)使用lock锁机制其中也包括相应的读写锁

悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自 外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。

乐观锁,大多是基于数据版本 Version )记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来 实现。 读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提 交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据 版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

乐观锁机制是在我们的系统中实现,来自外部系统的用户 余额更新操作不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。在 系统设计阶段,我们应该充分考虑到这些情况出现的可能性,并进行相应调整(如 将乐观锁策略在数据库存储过程中实现,对外只开放基于此存储过程的数据更新途 径,而不是将数据库表直接对外公开)。

【谨防在此,面试官会问到死锁的相关问题!!!关于死锁的问题,在其余某篇博客都有说明】

某航班只有一张机票,假定有1w个人打开你的网站来订票,问你如何解决并发问题(可扩展到任何高并发网站要考虑的并发读写问题)

假定我们采用了同步机制或者数据库物理锁机制,如何保证1w个人还能同时看到有票,显然会牺牲性能,在高并发网站中是不可取的。

采用乐观锁即可解决此问题。乐观锁意思是不锁定表的情况下,利用业务的控制来解决并发问题,这样即保证数据的并发可读性又保证保存数据的排他性,保证性能的同时解决了并发带来的脏数据问题。

如何实现乐观锁:

前提:在现有表当中增加一个冗余字段,version版本号, long类型

原理:

1)只有当前版本号>=数据库表版本号,才能提交

2)提交成功后,版本号version ++

首先,股票交易系统的行情表,每几秒钟就有一个行情记录产生,一天下来就有(假定行情3秒一个) 股票数量×20×60*6 条记录,一月下来这个表记录数量多大? 一张表的记录数超过100w后 查询性能就很差了,如何保证系统性能?

再比如,中国移动有上亿的用户量,表如何设计?把所有用于存在于一个表?

所以,大数量的系统,必须考虑表拆分-(表名字不一样,但是结构完全一样),通用的几种方式:(视情况而定)

1)按业务分,比如 手机号的表,我们可以考虑 130开头的作为一个表,131开头的另外一张表 以此类推

2)利用表拆分机制做分表

3)如果是交易系统,我们可以考虑按时间轴拆分,当日数据一个表,历史数据弄到其它表。这里历史数据的报表和查询不会影响当日交易。

此外,我们还得考虑缓存

这里的缓存独立于应用,依然是内存的读取,假如我们能减少数据库频繁的访问,那对系统肯定大大有利的。比如一个电子商务系统的商品搜索,如果某个关键字的商品经常被搜,那就可以考虑这部分商品列表存放到缓存(内存中去),这样不用每次访问数据库,性能大大增加。

1、可能是服务器网络带宽不够

2.可能web线程连接数不够

3.可能数据库连接查询上不去。

1、像第一种情况可以增加网络带宽,DNS域名解析分发多台服务器。

2、负载均衡,前置代理服务器nginx、apache等等

3、数据库查询优化,读写分离,分表等等

1、尽量使用缓存,包括用户缓存,信息缓存等,多花点内存来做缓存,可以大量减少与数据库的交互,提高性能。

2、用jprofiler等工具找出性能瓶颈,减少额外的开销。

3、优化数据库查询语句,减少直接使用hibernate等工具的直接生成语句(仅耗时较长的查询做优化)。

4、优化数据库结构,多做索引,提高查询效率。

5、统计的功能尽量做缓存,或按每天一统计或定时统计相关报表,避免需要时进行统计的功能。

6、能使用静态页面的地方尽量使用,减少容器的解析(尽量将动态内容生成静态html来显示)。

7、解决以上问题后,使用服务器集群来解决单台的瓶颈问题。

本文:Java中实现并发的方法有哪些的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:怎么使用Css制作按钮阴影效果下一篇:

3 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18