Java常见知识点总结-8.15

16 篇文章 0 订阅

整体以我的项目:任务分配策略管理系统为例

1、web项目用到的技术栈、主要负责的内容

作为项目负责人,一直跟踪项目的需求分析、原型设计、系统设计开发、测试、迭代开发以及算法研究和实现;

然后前端使用了BootStrap,使用Eclipse进行开发,使用了框架SpringMVC但是可能用的较浅,还在进行深入了解。

然后用到了多线程(多个用户进行任务执行,例如同时执行一个任务,那这时候,任务所需要的参与者需要进行变化,任务执行结束后,待执行任务的数据库需要发生变化)、IO优化(NIO)、MySQL数据库。然后后续主要实现数据库的优化以及并发;但是可能解决的方式较为简单。

主要进行了索引、sql语句的简单优化等。(引出索引和explain查询sql语句的执行情况进行优化分析)。

2、项目对应的数据库表有哪些

因为系统的模块主要为四块:个人中心、参与者管理、任务管理和任务分配策略管理。所以对应的数据库主要也是根据功能需要设计的数据表结构。其中数据库表大约有35个,然后主要的数据库表为参与者表、管理者表、任务表、任务策略信息表以及任务参与者匹配表。这里主要问题就行查询较多,所以需要进行数据库索引的建立,而且项目迭代过程中不断更新维护索引。

3、数据库用到的索引有哪些

因为任务分配策略中有较多的参与者表和任务表的查询,这两个表中都有很多属性需要多次进行访问,因为需要考虑参与者的约束(时间、位置、截止时间、参与者个数等)和任务的约束(时间、位置、可用时间、负载)、参与者的优先级(历史执行任务个数刻画的信誉度、移动距离、出行频率等)和任务的优先级(截止时间、重要程度等等)。

所以在参与者表中建立的索引,是根据经常做的查询,建立的多列符合索引,然后根据最左原则确定索引列的顺序;

在任务表中建立的索引,是根据匹配约束+匹配优先级所建立的符合多列索引;根据不同的策略和任务的不同属性,索引有所不同,因为任务类型不同所建的表不同,分为简单问答任务、简单传感任务以及复杂任务等等;

4、TCP为什么是三次握手,而不是两次

三次握手的目的是实现可靠性传输的前提条件,如果只有两次问题会出现一些问题。

1)在前两次握手的时候双方都随机选择了自己的初始段序号,并且第二次握手的时候 连接请求发送端收到了自己的ACKnumber,确认了自己的序列号,而连接请求响应端还没有确认自己的序列号,没有收到ACKnumber, 如果这时候两次握手下就进行数据传递, 序号没有同步,数据就会乱序。

2)三次握手能够防止已经过期的数据报被再次传到链接的手机。如果两次,很可能属性死锁,一方出现问题,另一方不知晓,一直等待,导致死锁。防止对方没有收到信号;

三次已经双方都确定通信,四次或者再多次就没有必要了。

5、多线程在项目中的应用以及使用过程

项目设计过程中会使用到很多多线程的情况,电商系统中就有大量的多线程设计,例如:同步商品信息和分类;用户静态任务、地址缓存同步、拼团锁单、解锁订单、取消顶戴;商品库存;消息的处理 店铺服务;

回归到该项目,在任务执行过程中,就是一个订单系统,订单提交后就要修改任务所需参与者个数以及任务的个数、任务执行个数等操作。多个任务的数据上传到平台,如果串行处理显然不能很好的使用多核的cpu处理器,于是考虑到使用多线程上传,线程太少会造成等待,线程过多会造成执行处理会让服务器崩溃。最终根据分析,选择了一次创建5个线程,然后这5个线程同时去抢占资源;

实现:

  1)可以使用锁把这段代码锁住,线程只有竞争到锁的使用权,才能对代码进行操作,让多线程排队一次操作这段代码,但是效率较低;

   2)使用乐观锁,对于上个线程处理后通知其他线程来执行这段代码,Tornado异步调用任务的工具,效率高,适合高并发。

   3)使用线程安全的集合存放资源ConcurrentLinkedQueue,是线程安全的集合,允许并发访问的数据结构的不同部分来使竞争极小。通过for循环然后实现Runable接口,实现创建线程;

     然后通过判断创建的所有线程都执行完毕,下面是两种方式:

     ExecutorService exec = Executors.newCachedThreadPool();//newCachedThreadPool可缓冲线程池

     final CountDownLatch endGate = new CountDownLatch(5);

  第一个将所有线程放在线程池;另一种是使用闭锁的方式、计数器,当计数器为0的适合,表示所有线程都执行完成。

6、项目中具体实现缓存的应用

  1)一开始数据量不是很大的时候,采用的是Map存储缓存,每次调用方法获取数据的时候,西安判断是否有缓存或者缓存是否过期,若缓存可用直接获取缓存中的数据。

就是将数据库查询的结果放到Map缓存中。

  2)数据量较大的情况

     通常会使用外部缓存+内部缓存;内部缓存自然是小而且过期时间快,外部缓存过期时间长。

    一开始内外缓存都没有预先存值,一个请求过来,查询某个数据,就开始查询内部缓存,有数据直接返回,没有数据就查询外部缓存,外部缓存得到数据就存入内部缓存,返回数据;外部缓存没有数据就查询数据库;数据库没有数据返回null,数据库有数据,存入外部缓存,存入内部缓存,返回值。

  3)Redis缓存

   缓存的目的为了提高系统的性能:热点数据,将经常访问的数据放在缓存中,降低数据库IO,同时缓存数据的高速查询,加速整个系统的响应速度,也能一定程度提高并发量;查询耗时的数据,较为耗时的数据就存放在缓存中,会极大提高系统响应速度,但是同时数据库的实时性较差;

   回归我的项目, 在进行任务数据的展示中,需要在看板中对数据进行汇总,汇总数据来自不同的数据库,各个数据的生成接口已经写好,就是调用接口整合数据进行返回。

 a、取mysql查询各个接口信息

List<PanelDto> panels = panelService.getAllPanels();   //得到接口的名称,接口的url

b、根据拿到的信息生成请求参数

细节类似于:https://www.cnblogs.com/jy107600/p/8110173.html

7、volatile原理和应用场景

常用于并发编程,具有可见性和防止指令重排序,不具备原子性;

volatile变量的赋值会刷入到主内存,并通知其他核心cpu,他们的缓存数据无效了,所有cpu核心在想对该变量操作首先会从主内存中重新拉取值,这保证对cpu操作的数据是最新的。

使用场景

1)状态变量

由于boolean的赋值是原子性的,所以volatile修饰布尔变量作为多线程停止标志简单有效;用来对线程接下来的逻辑进行控制

class Machine{
    volatile boolean stopped = false;

    void stop(){stopped = true;}
}

2)对象完整发布

单例对象的双重检验锁,对象的完整发布以来happens before原则;双检查锁机制。

防止对象溢出:安全发布对象;高效不可变对象;安全共享对象;

3)轻量级的读写锁策略

通过锁来实现独占写锁,使用volatile实现共享的读锁,多个线程可以同时读取数值;

8、InnoDB和MyIASM的区别和联系

详情:

https://blog.csdn.net/qq_27607965/article/details/79925288

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋葱ycy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值