我的随笔2

21.实现多线程有几种方式

1.继承 Thread 类
2.实现 Runnable 接口
3.实现 Callable 接口通过 FutureTask [ˈfjutʃər:f 又 曲~]包装器来创建线程。
4.使用线程池的方式来创建线程。如下://方式一:创建固定长度的线程池
ExecutorService executorService = newFixedThreadPool(5);

//方式二:创建一个可缓存的线程池
ExecutorService executorService1 = newCachedThreadPool();
//方式三:创建单个工作线程,能确保任务在队列中的顺序来串行执行ExecutorService executorService2 = newSingleThreadExecutor(); //方式四:创建延时固定长度的线程
ScheduledExecutorService scheduledExecutorService =
newScheduledThreadPool(5); //线程体

executorService.execute(new Thread() {

@Override
public void

run() {

System.out.println(“这是线程体”);

}

});

前两种无返回值,因为是通过重写 run 方法,run 方法返回结果是 void
第三种有返回值,没有怎么使用过,在该文档后面编码处提供了使用示例:

22.什么是线程安全

多线程访问同一代码,不会产生不确定的结果,这就是线程安全;
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

23.synchronized 和 volatile [ˈvɒlətʌɪl] 的区别是什么?

synchronized 可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到
临界区,同时它还可以保证共享变量的内存可见性
volatile 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量
的值,这新值对其他线程来说是立即可见的。
如果多个线程操作 volatile 修饰的变量,当其中一个线程对这个变量修改后,它会将其他线程工作内存中该变量的数据设为失效状态,迫使其他线程重新从主程序中读取该变量数据,从而实现可见性
volatile 本质是在告诉 jvm 当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取
volatile 仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的。volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变
量的修改可见性和原子性。
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞。
volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化。

24.Cookie,Sesssion 区别

1、数据存放位置不同,cookie 数据存放在客户的浏览器上,session 数据放在服务器上。
2、安全程度不同,别人可以分析存放在本地的 cookie 并进行 cookie 欺骗,cookie 不是很安全
3、性能使用程度不同,session 会在一定时间内保存在服务器上。当访问增多,会比较
占用你服务器的性能
4、数据存储大小不同,单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个站点最多保存 20 个 cookie。
5、所以个人建议:
将登陆信息等重要信息存放为 SESSION
其他信息如果需要保留,可以放在 COOKIE 中
Cookie 欺骗介绍:对用户的 cookie 进行改写达到欺骗服务程序的目的

25.sleep 和 Wait 的区别

sleep()方法(休眠)是线程类(Thread)的静态方法,调用此方法会让当前线程暂停执行指定的时间,将执行机会(CPU)让给其他线程,但是对象的锁依然保持,因此休眠时间结束后会自动恢复。
wait()是 Object 类的方法,它会导致当前线程放弃对象的锁(线程暂停执行),进入对象的等待池(wait pool),只有调用对象的 notify()方法(或 notifyAll()方法)时才能唤醒等待池中的线程进入等锁池(lock pool),如果线程重新获得对象的锁就可以进入就绪状态。
Join()是暂停当前正在执行的线程,强制执行使用 Join()方法的线程,直到该线程执行结束
Yield()线程礼让,把执行机会让给其他线程,只是提供一种可能

26.给我讲一下同步和异步的区别

同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。
当有消息返回式系统会通知进程进行处理,这样可以提高执行的效率。
同步是阻塞模式,异步是非阻塞模式。

27.什么是死锁?如何避免

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务

一种非常简单避免死锁的方式就是:指定获取锁的顺序,并强制线程按指定顺序获取锁,因此,如果所有的线程都是以同样的顺序加锁和释放锁,就不会出现死锁了

28.基础类型各自所占的字节数

byte: 1 字节short:2 字节char:2 字节float:4 字节int:4 字节
boolean:取决于虚拟机,1 字节或 4 字节
double:8 字节long:8 字节

29.抽象类(abstract class)和接口(interface)有什么异同

抽象类使用 abstract 关键字修饰;接口使用 interface 修饰。
抽象类中有构造方法(不写会有隐式构造方法),但不能实例化;接口没有构造方法。抽象类中可以有非抽象方法,接口中一般只有抽象方法。
抽象类中可以有变量;接口中只能是常量
实现类只能继承一个抽象类;但可以实现多个接口

30.Error 和 Exception 有什么区别

Error 和 Exception 都实现了 Throwable 接口
Error 指的是 JVM 层面的错误,比如内存不足 OutOfMemoryError Exception 指的是代码逻辑的异常,比如下标越界 OutOfIndexException

31.什么是值传递和引用传递

值传递是在方法被调用时,实参通过形参把它的内容副本传入方法内部,此时方法接收到的内容是实参值的一个拷贝,因此在方法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
引用传递一般是在方法调用时,实参的引用地址会通过方法调用被传递给相应的形参,
在方法体内,形参和实参指向同一个内存地址,对形参的操作会影响实参的实际内容一般认为,java 内的基础类型数据传递都是值传递,实例对象和的传递都是引用传递

32.final, finally, finalize 的区别

final 修饰类 表示该类不能被继承

修饰方法 表示该方法不能被重写
修饰基本类型变量 表示该变量只能被赋值一次
修饰引用 表示该引用只有一次指向对象的机会
finally 是用于异常处理的场面,无论是否有异常抛出,都会执行
finalize 是Object 类中提供的方法。 当一个对象满足垃圾回收的条件,并且被回收的时候,其 finalize()方法就会被调用

33.String 的常用方法有哪些?

indexOf():返回指定字符的索引。charAt():返回指定索引处的字符。replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。length():返回字符串长度。toLowerCase():将字符串转成小写字母。toUpperCase():将字符串转成大写字符。substring():截取字符串。
equals():字符串比较。

34.请说出几个 Object 类中的方法及其说明

registerNatives() //私有方法

getClass() //返回此 Object 的运行类。

hashCode() //用于获取对象的哈希值。

equals(Object obj) //用于确认两个对象是否“相同”。

clone() //创建并返回此对象的一个副本。

toString() //返回该对象的字符串表示。

notify() //唤醒在此对象监视器上等待的单个线程。

notifyAll() //唤醒在此对象监视器上等待的所有线程。

wait(long timeout) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或

者超过指定的时间量前,导致当前线程等待。

wait(long timeout, int nanos) //在其他线程调用此对象的 notify() 方法或 notifyAll()

方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程
等待。

wait() //用于让当前线程失去操作权限,当前线程进入等待序列

finalize() //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调
用此方法。

35.Redis 是什么?怎么使用

Redis 是一个开源的、基于内存的高性能 key-value 数据库.而且支持保存多种数据结构, 如字符串、列表、哈希、集合、有序集合,支持持久化、过期时间、事务
我用的是用它来缓存热数据,在查看数据库之前先查询 Redis,有该数据的话使用
Redis 数据,放弃查询数据库,没有的话,查询数据库,然后将数据插入 Redis
一般来讲把经常用来查询、不经常修改的信息存到 redis 里

36.Redis 持久化策略

redis 提供了两种内存数据持久化到文件的方式,
一种是 RDB(Redis DataBase)持久化机制,它是保存某个时间点的全量数据快照,默
认执行此种方式,默认的文件名为 dump.rdb
另一种是 AOF(Append-Only-File)持久化机制,记录下除了查询以外的所有变更数据库状态的指令,以 append 的形式追加保存到 AOF 文件中
当在redis.config 配置文件中开启AOF 持久化机制时,redis 在启动时,会优先载入AOF文件。其中服务器在载入文件的过程中处于阻塞状态。

37.什么是事务

事务是作为单个逻辑工作单元执行的一系列操作,多个操作作为一个整体向系统提交,要么都执行、要么都不执行 ,事务是一个不可分割的工作逻辑单元

38.事务的 ACID(四大特性)是指什么?

原子性(Atomic):事务中各项操作,要么全做要么全不做,任何一项操作的失败都会导致整个事务的失败;
一致性(Consistent):事务结束后系统状态是一致的;
隔离性(Isolated):并发执行的事务彼此无法看到对方的中间状态;
持久性(Durable):事务完成后所做的改动都会被持久化,即使发生灾难性的失败。通过日志和同步备份可以在故障发生后重建数据。

39.索引的类型

普通索引:最基本的索引,它没有任何限制,用于加速查询。
index index_name(“字段”)
唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必

须唯一。 unique index_name(“字段”)

主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是

在建表的时候同时创建主键索引。 primary key(“id”):设置主键即可

复合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个
字段,索引才会被使用。使用组合索引时遵循最左前缀集合。
index index_name(“字段一”,“字段二”)

全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。
fulltext(“关键字”)
主键索引和唯一索引的区别:

  1. 主键索引不能为空…
  2. 在一张表中主键索引只能有 1 个…唯一索引可以有多个

40.索引的优缺点?

优点:索引能够提高数据检索的效率,降低数据库的 IO 成本。
缺点:索引其实也是一张表也占空间,需要时间建立索引,顾增删改速度降低

41.数据库的索引以什么为主,为什么

索引在 Mysql 数据库中分三类,B+数、Hash 索引、全文索引,而 Mysql 的索引主要是以 B+树为主,要介绍 B+树,就不得不提二叉查找树、平衡二叉树和 B 树这三种数据结构,B+树就是从他们仨演化而来
二叉查找树:
特点:任何节点的左子节点的键值都小于当前节点的键值,右节点的键值都大于当前节点的键值,顶端的节点我们称之为根节点,没有子节点的节点我们称之为叶节点
查找步骤:若根节点的关键字值等于查找的关键字,则查找成功,否则,若小于根节点的关键字值,递归查左子树,若大于根节点的关键字值,递归查右子树,若子树为空,则查找不成功
缺点:如果二叉树数据不平衡,也就是高度太高了,会导致查找效率的不稳定,为了解决这个问题,需要让树保证平衡,这时平衡二叉树就出来了
平衡二叉树
特点:平衡二叉树又称 AVL 树,在满足二叉查找树特性的基础上,要求每个节点的左右子树的高度不能超过 1,它保证了树的构造时平衡的,当我们插入或者删除数据导致树不平衡时,平衡二叉树会进行调整树上的节点来保持平衡
它相对于二叉查找树来说,查找效率更稳定,总体查找速度也更快
缺点:平衡二叉树每个节点只存储一个键值和数据的,如果使用它作为索引的数据结构,那我们每查找一个数据就需要从磁盘中读取一个节点,但是如果是海量数据呢,那可以想象到二叉树的节点将会非常多,高度也特点高,那么查找数据时就会进行很多次磁盘 IO,查找数据的效率将会极低,为了解决平衡二叉树的这个弊端,我们应该寻找一种可以存储多个键值和数据的平衡树,也是 B 树
B 树:
特点:B 树相对于平衡二叉树,每个节点存储了更多的键值和数据,每个节点拥有了更多的子节点,因为 Mysql 读取的基本单位是页,所以我们
将这里的单个节点称之为页,这样更符合 Mysql 中索引的底层数据结构,基于这个特性,B 树查找数据读取磁盘的次数将会减少,数据查找效率也会比平衡二叉树高很多

B+树:

特点:是 B 树的进一步优化,因为数据库中页的大小是固定的,B+树的非叶子节点是不存储数据的,仅存储键值,而 B 树节点中不仅存储键值,也存储数据,在页大小固定的情况下,B+树不存数据,那么就可以存储更多的键值,相对的树的阶数就会更大,那么查找时进行 IO 次数又会再次减少,数据查询的效率也会更快,
而且 B+树索引的所有数据均存储在叶子节点上,而且数据是按顺序排列的,这使得 B+树的范围查找、排序查找、分组查找以及去重查找变得异常简单,B 树因为数据分散在各个节点,要实现这一点并不容易

42.什么会导致索引失效

1.以%开头的 LIKE 查询不能使用 BTREE 索引
2.数据类型出现隐式转换时也不能使用索引
3.复合索引时 不符合最左匹配原则(上面已经提到)
4.用 or 分隔开的条件,如果 or 前的条件中的列有索引,后面的列中没有索引,那么涉及到的索引都不会使用到
5. order by 字段混合使用 DESC ASC 不会使用索引

43.Mysql 的存储引擎

存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据,不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能
Mysql 支持很多种存储引擎,包括 InnoDB,MyISAM ,Memory ,Merge 等,
区别体现在事务安全,空间、内容使用,插入数据速度和对外键的支持上
MyISAM: 5.5 版本之前默认的存储引擎,全表锁,不支持事务,不支持外键,并发性能
差,占用空间较小。但拥有较高的插入、查询速度
InnoDB:是 Mysql5.5 版本及之后默认的存储引擎,行级锁,提供了具有提交、回滚和
奔溃恢复能力的事务安全,支持外键,行级锁,支持自动增长列,并发能力强;
Memory:将表中的数据存储到内存中,速度快,但会占用和数据量成正比的内存空间
且数据在 mysql 重启时会丢失。

44.mysql 问题排查都有哪些手段?

1.使用 show processlist 命令查看当前所有连接信息。
2.使用 explain 命令查询 SQL 语句执行计划。
执行计划,里面有个字段 type,它所对应的 value 如下(性能由差到好)
ALL: 全表扫描index: 索引全扫描range: 索引范围扫描
ref: 使用非唯一索引扫描eq_ref: 使用唯一索引扫描

const,system: 单表中最多只有一个匹配行null
3. 开启慢查询日志,查看慢查询的 SQL。
在配置文件添加如下信息:

slow_query_log=“ON” # 是否开启慢查询日志,默认 OFF

slow_query_log_file=“文件路径” #慢查询日志文件存储位置

log_queries_not_using_indexes=“ON” #是否把没有使用到索引的SQL记录到日志中,默认OFF

long_query_time=1 #超过多少秒的查询才会记录到日志中,注意单位是秒

45.Mysql 语句运行时间过长优化

1、查看 sql 是否涉及多表的联表或者子查询,如果有,看能否进行业务拆分,
2、对于数据量大,而且要经常查询的表,给其建立相应的索引,加快查询速度
3、针对数据量大的表进行历史表分离
4、少用 select * ,应尽量避免全表扫面
6、合理使用批处理
7、选择正确的存储引擎
8、看 mysql 的执行计划(explain),看是否有使用到索引

46.数据库的优化策略

1、表结构优化
表结构优化是数据库优化中最重要的,需要结合实际情况来看怎么设计更加的优化合

2,sql 语句优化
sql 语法优化,写出更加便捷的 sql 语句
处理逻辑优化,如配合索引和缓存的使用
3,分区分表
分区是指将一张表的数据按照一定的规则分到不同的区来保存。若一张表中有几种类
型,可以考虑分表
举一个例子,分区按照月份来分,将不同类型的字段分表,这么做的好处就是增删改
查数据的时候范围已经大大缩小了
4,索引优化
索引的原理是在进行增删改的时候就预先按照指定的字段顺序排列后保存了,在查找
的时候就可以从索引找到对应的指针找到数据
优点:查询效率很高 缺点:每次增删改要更新索引,降低增删改的速度5,分离活跃数据
将活跃数据单独存放起来
比如登录网站,可以将活跃度高的用户单独存放(依据最近登录时间或者单位时间内登
录次数等),查询时先从活跃数据查找,没有再去不活跃处查找
6,读写分离
读写分离的本质是对数据库进行集群,在高并发的情况下降低单台服务器的压力。

一般将写的服务器叫主服务器,写入后同步到读服务器(即从服务器),并将读请求分
配到多个服务器上

47.数据库的隔离级别?

读未提交(read-uncommitted):最低隔离级别、事务未提交前,就可被其他事务读取(会出现脏读、不可重复读、幻读)
读提交(read-committed):一个事务提交后才能被其他事务读取到(会造成不可重复
读、幻读)
可重复读(repeatable-read):默认级别,保证多次读取同一个数据时,其值都和事务
开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)
串行化(serializable):代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。
脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插
入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。
不可重复读 :是指在一个事务内,多次读同一数据。读取到的结果不一致
幻读:指同一个事务内多次查询返回的结果集不一样。比如,事务 A 先后读取同一范围的记录,此时事务 B 在这个时候插入了一条记录,导致两个读取的记录数不同就好像发生了幻觉一样,这就叫幻读。
小结:不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增和删除。

48.数据库的三大范式?

第一范式:确保每列的原子性,即每个属性都是最基本的数据项
第二范式:确保每列都和主键相关,即一张表只描述一件事。第三范式:即每个属性都跟主键有直接关系而不是间接关系

49.数据库的存储过程

存储过程一般就是把一些对数据库的操作汇集成一个过程,以后每次执行业务时,只需调用这个存储过程即可,这样能提升代码的可重用性
但它移植性能差、而且不易调试,
而且项目中有大批量的数据操作时,我们发现 jdbc 的批处理方式的性能要比存储过程
的好,所以项目中并没有怎么用
基本语法:
创建存储过程:delimiter //
Create procedure procedure_name()
Begin
Select * from teble_name End //

使用存储过程: call procedure_name();
删除存储过程: drop procedure procedure_name;
参考网址:https://segmentfault.com/a/1190000018264669 Procedure [prəˈsidʒər] 程序

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值