基础知识杂项

1. 悲观锁乐观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,再比如Java里面的同步原语synchronized关键字的实现也是悲观锁

乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适

悲观锁机制存在以下问题:

1.在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。

2.一个线程持有锁会导致其它所有需要此锁的线程挂起。

3.如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。

对比于悲观锁的这些问题,另一个更加有效的锁就是乐观锁。其实乐观锁就是:每次不加锁而是假设没有并发冲突而去完成某项操作,如果因为并发冲突失败就重试,直到成功为止


1.1. 乐观锁实现的两种机制

乐观锁的机制其实就是冲突检查+数据更新

版本号机制或CAS算法实现


1.1.1. 版本号机制

一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功

举一个简单的例子: 假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。

操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 50 100-$50 )。

在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 20 100-$20 )。

操作员 A 完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣除后余额( balance=$50 ),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。

操作员 B 完成了操作,也将版本号加一( version=2 )试图向数据库提交数据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为 2 ,数据库记录当前版本也为 2 ,不满足 “ 提交版本必须大于记录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回

这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员 A 的操作结果的可能


1.1.2. CAS算法

CAS是乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试

CAS 操作中包含三个操作数 —— 需要读写的内存位置(V)进行比较的预期原值(A)拟写入的新值(B)。如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B。否则处理器不做任何操作。无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)CAS 有效地说明了“ 我认为位置 V 应该包含值 A;如果包含该值,则将 B 放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可。 ”这其实和乐观锁的冲突检查+数据更新的原理是一样的

这里再强调一下,乐观锁是一种思想。CAS是这种思想的一种实现方式


2. MQ

消息队列(MQ)是一种应用程序对应用程序的通信方法。应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们。消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信,直接调用通常是用于诸如远程过程调用的技术(如:WebService)。排队指的是应用程序通过队列来通信。队列的使用除去了接收和发送应用程序同时执行的要求


2.1. 用MQ的原因

1.调用异步化,提高服务器性能

在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发的情况下会对数据库造成巨大的压力,同时也使得响应延迟加剧。在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程(通常该进程独立部署在专门的服务器上)从消息中获取数据,异步写入数据库。由于消息队列服务器处理速度远远快于数据库,因此用户的相应延迟得到有效改善

不使用MQMQ1

使用MQMQ2

消息队列还具有很好的削峰作用,通过异步请求,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。在电商网站促销,秒杀活动中,合理使用消息队列,可有效抵御促销活动刚开始大量涌入的订单对系统造成的冲

2.利用分布式消息队列可以降低系统耦合性

如果模块之间不存在直接调用,那么新增模块或者修改模块就对其他模块影响最小,这样系统的可扩展性无疑更好


2.2. MQ介绍的补充

在互联网应用中,基本都会有用户注册的功能。

在注册的同时,我们会做出如下操作:

1.收集用户录入信息,保存到数据库

2.向用户的手机或邮箱发送验证码 等等…

如果是传统的集中式架构,实现这个功能非常简单:开启一个本地事务,往本地数据库中插入一条用户数据,发送验证码,提交事物

但是在分布式架构中,用户和发送验证码是两个独立的服务,它们都有各自的数据库,那么就不能通过本地事物保证操作的原子性。

这时我们就需要用到 ActiveMQ(消息队列)来为我们实现这个需求。 在用户进行注册操作的时候,我们为该操作创建一条消息,当用户信息保存成功时,把这条消息发送到消息队列。 验证码系统会监听消息,一旦接受到消息,就会给该用户发送验证码

如何防止消息重复发送?

解决方法很简单:增加消息状态表。通俗来说就是一个账本,用来记录消息的处理状态,每次处理消息之前,都去状态表中查询一次,如果已经有相同的消息存在,那么不处理,可以防止重复发送


2.3. MQ的应用场景

1.电商促销、秒杀相关活动的用户请求处理,有效削减高并发

2.如阿里旅行、去哪儿类似的订票系统,下单支付完成后,并不是立即返回出票成功,而是等铁路、航空公司处理完成才收到短信提示出票成功

3.短信验证码、邮件激活等实时性要求不高(验证码一般是60/120秒的等待时间,邮件激活一般是24小时)的功能都可以用MQ,大不了超时收不到,让用户点击重新发送


2.4. MQ的相关产品介绍

1.ActiveMQ 是Apache下的一个子项目,类似ZeroMQ,它能够以代理人和点对点的技术实现队列。同时类似于RabbitMQ,它少量代码就可以高效地实现高级应用场景,支持多种语言客户端

2.ZeroMQ 号称最快的消息队列系统,尤其针对大吞吐量的需求场景

3.RabbitMQ 本身支持很多的协议,正是如此,使的它变的非常重量级,更适合于企业级的开发


2.5. MQ和Dubbo的异同

1.dubbo和MQ**都是为了解决分布式应用之间的通信问题**

2.dubbo使用的RPC,侧重于同步调用,客户端会依赖服务端提供的接口然后进行调用

3.MQ使用的是观察者模式,消息发送者只负责产生并发送消息,消息消费者只负责接收消息并做相应处理,两者并不知道对方的存在,侧重于异步通信,耦合性较低

4.MQ是消息队列,一个程序把内容放到队列里,另外一个程序过来消费

5.例如用户登录服务,客户端传输用户名和密码到服务器端,服务器端验证帐号密码是否正确,并把结果返回给客户端,这种交互形式使用dubbo

6.例如需要进行用户行为收集,客户端只需不断把行为日志收集,这种方式使用MQ,先把行为日志发送到MQ,再由消息消费者统一批量存储到数据中心

7.需要对方及时作出响应,就用RPC;受众有多方,就用MQ


2.6. JMS

Java Message Service

消息服务分为

PTP模式 点对点模式 一个生产者和一个消费者一一对应

Pub/Sub 发布订阅模式 一个生产者产生消息并进行发送后,可以由多个消费者进行接收


2.6.1. PTP模式

点对点模式,数据只有一个,一个人拿完了另外一个就拿不了了Quene

生产者

创建连接工厂
获取连接
获得session
创建队列
创建要发送的信息
发送信息
关闭资源

消费者

创建连接工厂
获取连接
获得session
创建队列
创建消费者
创建监听器,在监听器内显示数据

2.6.2. 发布订阅模式

将PTP中的创建队列,Quene变成Topic就可以了
注意要先启动消费者,然后启动生产者
多个消费者都是可以得到数据的


2.7. ActiveMQ 如果消息发送失败怎么办

Activemq 有两种通信方式,点到点形式和发布订阅模式

如果是点到点模式的话,如果消息发送不成功此消息默认会保存到 activemq 服务端知道有消费者将其消费,所以此时消息是不会丢失的。

如果是发布订阅模式的通信方式,默认情况下只通知一次,如果接收不到此消息就没有了。这种场景只适用于对消息送达率要求不高的情况。如果要求消息必须送达不可以丢失的话,需要配置持久订阅。每个订阅端定义一个 id, 在订阅是向 activemq 注册。发布消息和接收消息时需要配置发送模式为持久化。此时如果客户端接收不到消息,消息会持久化到服务端,直到客户端正常接收后为止。


3. Redis

Redis可基于内存亦可持久化的日志型、Key-Value形式的Nosql(非关系型数据库)数据库,Redis是缓存服务器,mySql是关系型数据库,mySql不能解决高并发问题,关系型数据库把数据存在磁盘上,持久化存储,redis将数据存在内存,有时效性,时效性会造成数据丢失


3.1. 使用Redis的原因

网站性能优化第一定律:优先使用缓存优化性能,而redis作为Nosql数据库是首选


3.2. Redis优势

1.性能极高 Redis读的速度是110000次/s,写的速度是81000次/s

2.丰富的数据类型 Redis支持string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)数据类型操作

3.使用简单 Redis的数据类型都是基于基本数据结构的同时对程序员透明,无需进行额外的抽象(可简单理解为redis已经实现好多种数据结构,程序员无需再去实现,直接使用即可)。

4.原子性 Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

5.丰富的特性 Redis还支持 publish/subscribe, 通知, key 过期等等特性。

6.支持数据的备份 即master-slave模式的数据备份(主从复制)。

7.支持数据的持久化 可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。(所以在对不同数据集进行高速读写时需要权衡内存,应为数据量不能大于硬件内存)


3.3. Redis缺点

1.由于是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小有关。虽然 redis 本身有 key 过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据。

2.如果进行完整重同步,由于需要生成 rdb 文件,并进行传输,会占用主机的 CPU,并会消耗现网的带宽。 不过 redis2.8 版本,已经有部分重同步的功能,但是还是有可能有完整重同步的。比如,新上线的备机。

3.修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中, redis不能提供服务。


3.4. Redis应用场景

适用于数据变化快且数据库大小可预见(合适内存容量)的应用程序

1.缓存(数据查询、短连接、新闻内容、商品内容等等)。(使用最多)

2.分布式集群架构中的session分离(咱们在项目学习中的单点登录系统中的运用)聊天室的在线好友列表

3.任务队列(秒杀、抢购、12306等)redis本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用

4.数据过期处理(可以精确到毫秒)


3.5. Redis持久化

RDB 持久化:该机制可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)

AOF 持久化:记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 AOF 文件中的命令全部以 Redis 协议的格式来保存,新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件 进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小

无持久化:让数据只在服务器运行时存在

同时应用 AOF 和 RDB:当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整


3.5.1. RDB 的优缺点

优点

RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集。 这种文件非常适合用于进行备份: 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。 RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑,可以(在加密后)将它传送到别的数据中心,或者亚马逊 S3 中。 RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。 RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

缺点

如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为 RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。每次保存 RDB 的时候, Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。 在数据集比较庞大时, fork() 可能会非常耗时,造成服务器在某某毫秒内停止 处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒


3.5.2. AOF 的优缺点

优点

使用 AOF 持久化会让 Redis 变得非常耐久(much more durable):你可以设置不同的 fsync 策略,比如 无 fsync ,每秒钟一次 fsync ,或者每次执行写入命令时 fsync 。 AOF 的默认策略为每秒钟 fsync 一次,在这种配置下, Redis 仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据( fsync 会在后台 线程执行,所以主线程可以继续努力地处理命令请求)。 AOF 文件是一个只进行追加操作的日志文件(append only log), 因此对 AOF 文件的写入不需要进行 seek , 即使日志因为某些原因而包含了未写入完整的命令(比如写入 时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。

Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。而一旦新 AOF 文件创建完毕, Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作

缺点

对于相同的数据集来说, AOF 文件的体积通常要大于 RDB 文件的体积。根据所使用的 fsync 策略, AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时, RDB 可以提供更有保证的最大延迟时间 (latency)

AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复 成保存时的原样。 (举个例子,阻塞命令 BRPOPLPUSH 就曾经引起过这样的 bug 。) 测试套件里为这种情况添 加了测试: 它们会自动生成随机的、复杂的数据集, 并通过重新载入这些数据来确保一切正常。 虽然这种 bug 在 AOF 文件中并不常见, 但是对比来说, RDB 几乎是不可能出现这种 bug 的


4. Nginx

Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器


4.1. 应用场景

1.http服务器。Nginx是一个http服务可以独立提供http服务。可以做网页静态服务器。

2.虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。

基于端口的,不同的端口

基于域名的,不同域名

3.反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。


4.2. 反向代理

当我们有一个服务器集群,并且服务器集群中的每台服务器的内容一样的时候,同样我们要直接从个人电脑访问到服务器集群服务器的时候无法访问,必须通过第三方服务器才能访问集群

这个时候,我们通过第三方服务器访问服务器集群的内容,但是我们并不知道是哪一台服务器提供的内容,此种代理方式称为反向代理


4.3. 负载均衡

公司会建立很多的服务器,这些服务器组成了服务器集群,然后,当用户访问网站的时候,先访问一个中间服务器,再让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入选择的服务器

所以,用户每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况


5. Dubbo

Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册)

其核心部分包含:

1.远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。

2.集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。

3.自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

Dubbo的连接方式

Dubbo 的客户端和服务端有三种连接方式,分别是:广播,直连和使用 zookeeper 注册中心


5.1. Dubbo作用

1.透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入

2.软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点

3.服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者


5.2. Dubbo调用关系

0.服务容器负责启动,加载,运行服务提供者。

1.服务提供者在启动时,向注册中心注册自己提供的服务。

2.服务消费者在启动时,向注册中心订阅自己所需的服务。

3.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

5.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。


5.3 zookeeper

zookeeper调用方式

调用关系说明:

1)服务容器负责启动,加载,运行服务提供者。

2)服务提供者在启动时,向注册中心注册自己提供的服务。

3)服务消费者在启动时,向注册中心订阅自己所需的服务。

4)注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

5)服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

6)服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。


6. 设计模式

6.1. 单例和多例

单例模式的关键有两点

1.构造方法为私有,这样外界就不能随意调用。

2.get的方法为静态,由类直接调用

多例模式(Multiton)

1 、多例类可以有多个实例

2 、多例类必须能够自我创建并管理自己的实例,并向外界提供自己的实例


6.2. 单例和多例的详细描述

1.什么是单例多例所谓单例就是所有的请求都用一个对象来处理,比如我们常用的service和dao层的对象通常都是单例的,而多例则指每个请求用一个新的对象来处理,比如action

2.如何产生单例多例

在通用的SSH中,单例在spring中是默认的,如果要产生多例,则在配置文件的bean中添加scope=”prototype”

3.为什么用单例多例

之所以用单例,是因为没必要每个请求都新建一个对象,这样子既浪费CPU又浪费内存

之所以用多例,是为了防止并发问题;即一个请求改变了对象的状态,此时对象又处理另一个请求,而之前请求对对象状态的改变导致了对象对另一个请求做了错误的处理

用单例和多例的标准只有一个

当对象含有可改变的状态时(更精确的说就是在实际应用中该状态会改变),则多例,否则单例;

4.何时用单例?何时用多例?

对于struts2来说,action必须用多例,因为action本身含有请求参数的值,即可改变的状态;

而对于STRUTS1来说,action则可用单例,因为请求参数的值是放在actionForm中,而非action中的

另外要说一下,并不是说service或dao一定是单例,标准同第3点所讲的,就曾见过有的service中也包含了可改变的状态,同时执行方法也依赖该状态,但一样用的单例,这样就会出现隐藏的BUG,而并发的BUG通常很难重现和查找


7. SOA

需要按照功能点把系统拆分,拆分成独立的功能。单独为某一个节点添加服务器。需要系统之间配合才能完成整个业务逻辑,叫做分布式


7.1. 优点

1.把模块拆分,使用接口通信,降低模块之间的耦合度

2.把项目差分成若干子项目,不同的团队负责不同的子项目

3.增加功能是只需要在增加一个子项目,调用其他系统的接口就好了

4.可以灵活进行分布式部署


7.2. 缺点

1.系统之间需要使用远程通信,接口开发,增加工作量

2.各个模块有一些通用的业务逻辑无法公用


8. Zookeeper

ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,ZooKeeper 的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户


9. 多线程

多线程的意义它可以让程序在一个时间段执行多个事情,提高了应用程序的使用率

创建线程
    使用thread类和Runnable接口,使用Callable和Future接口创建线程
        继承Thread类,然后重写run方法,将需要执行的代码,放到run中
            然后对象调用start方法,开启线程
        实现(implements) Runnable接口,重写所实现接口的run方法,并将线程执行代码存放在run方法中
            创建Thread对象,调用start方法,启动线程
        具体是创建Callable接口的实现类,并实现call()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程
            Callable和Future一个产生结果,一个拿到结果
    推荐使用实现接口的方法,因为继承thread类之后,该类就不能继承别的类了,会提高耦合性

线程的五中基本状态

线程的五种基本状态
    新建状态
        当线程对象对创建后,即进入了新建状态
    就绪状态
        当调用线程对象的start()方法,线程处于就绪状态,等待CPU调度执行
            就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中
    运行状态
        当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态
    阻塞状态
        处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态
            等待阻塞
                运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态
            同步阻塞
                线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态
            其他阻塞
                通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态
    死亡状态
        线程执行完了或者因异常退出了run()方法,该线程结束生命周期

数据库

MySql

mysql中四个存储引擎: innodb、myisam、memory、archive

MySql的事物隔离级别

事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

mysql的默认隔离级别是可重复读


MySQL中myisam与innodb的区别

    1>.InnoDB支持事物,而MyISAM不支持事物
    2>.InnoDB支持行级锁,而MyISAM支持表级锁
    3>.InnoDB支持MVCC, 而MyISAM不支持
    4>.InnoDB支持外键,而MyISAM不支持
    5>.InnoDB不支持全文索引,而MyISAM支持。

    InnoDB提供提交、回滚、崩溃恢复能力的事务安全(ASID)能力,实现并发控制。

    MyISAM提供较高的插入和查询记录的效率,主要用于插入和查询。

    memory用于临时存放数据,数据量不大并且不需要较高数据安全性。

    archive:如果只有插入和查询可以用,支持高并发的插入操作,但本身不是事务安全。

2者select count(*)哪个更快

MyISAM更快,因为MyISAM内部维护了一个计数器,可以直接调取

mysql中视图和表的区别以及联系

区别:

(1)视图是已经编译好的SQL语句,是基于SQL语句的结果集的可视化的表,而表不是。

(2)视图没有实际的物理记录,而表有。

(3)视图是窗口,表是内容。

(4)视图是逻辑概念的存在,不占用物理空间;而表占用物理空间。

(5)表可以及时对它进行修改;而视图只能用创建语句来修改。

(6)视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些SQL语句的集合。

(7)从安全来说,视图可以防止用户直接接触表,因而用户不知道表结构。

(8)表属于全局模式中的表,是实表;视图属于局部模式的表,是虚表。

(9)视图的建立和删除只影响视图本身,不影响对应的表。

联系:

      视图是在表之上建立的虚表,它的结构(所定义的列)和内容(所有记录)都来自表,视图依据表存在而存在。一个视图可以对应多个表。视图是表的抽象和在逻辑意义上建立的新关系。

      删除视图中的数据,数据库中表的数据会一起被删除。

关系型数据库的特点

1)数据集中控制。在文件管理方法中,文件是分散的,每个用户或每种处理都有各自的文件,这些文件之间一般是没有联系的,因此,不能按照统一的方法来控制、维护和管理。而数据库则很好地克服了这一缺点,可以集中控制、维护和管理有关数据。
2)数据独立性高。数据库中的数据独立于应用程序,包括数据的物理独立性和逻辑独立性,给数据库的使用、调整、优化和进一步扩充提供了方便,提高了数据库应用系统的稳定性。
3)数据共享性好。数据库中的数据可以供多个用户使用,每个用户只与库中的一部分数据发生联系;用户数据可以重叠,用户可以同时存取数据而互不影响,大大提高了数据库的使用效率。
4)数据冗余度小。数据库中的数据不是面向应用,而是面向系统。数据统一定义、组织和存储,集中管理,避免了不必要的数据冗余,也提高了数据的一致性。
5)数据结构化,整个数据库按一定的结构形式构成,数据在记录内部和记录类型之间相互关联,用户可通过不同的路径存取数据。
6)统一的数据保护功能,在多用户共享数据资源的情况下,对用户使用数据有严格的检查,对数据库规定密码或存取权限,拒绝非法用户进入数据库,以确保数据的安全性、一致性和并发控制。

Orcal

Orcal事务的隔离级别

. 脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×

SVN

svn是什么

SVN(subversion)是近年来崛起的版本管理工具,是cvs的接班人。目前,绝大多数开源软件都使用SVN作为代码版本管理软件。不要狭义的理解只服务于软件研发,很多公司都适用SVN管理整个公司的文档

猜你喜欢

转载自blog.csdn.net/weixin_42857002/article/details/82468885