static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法:
- 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享;
- 用来修饰成员方法,将其变为类方法,可以直接使用**“类名.方法名”**的方式调用,常用于工具类;
- 静态块用法,将多个类成员放在一起初始化,使得程序更加规整,其中理解对象的初始化过程非常关键;
- 静态导包用法,将类的方法直接导入到当前类中,从而直接使用**“方法名”**即可调用类方法,更加方便。
- 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
- 用来修饰方法参数,表示在变量的生存期中它的值不能被改变;
- 修饰方法,表示该方法无法被重写;
- 修饰类,表示该类无法被继承。
第三种和第四种方法需要谨慎使用,因为在大多数情况下,如果是仅仅为了一点设计上的考虑,我们并不需要使用final来修饰方法和类。
3、线程- 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止(TERMINATED):表示该线程已经执行完毕。
1.创建状态:通过继承Thread类或者实现Runnable接口的方法新建一个线程类,然后new一个该线程类的对象;
2.就绪状态:线程类对象执行start()方法,可以使线程进入就绪队列,等待cpu资源(cpu时间片);
当处于就绪状态的线程获得cpu资源时,会进入运行状态,即执行该线程;
当处于运行状态的线程时间片用完后,会退回到就绪状态,等待cpu资源;
当处于阻塞状态的线程,阻塞解除时也会变成就绪状态,进入就绪队列;
3.运行状态:就绪状态的线程获得了cpu资源就成为了运行状态,执行程序体;
4.阻塞状态:线程因为某种原因放弃cpu使用权,除非解除阻塞,重新进入就绪状态,有三种阻塞情况:
(1)等待阻塞:运行的线程,执行wait()方法,系统会进入阻塞状态
(2)同步阻塞:运行的线程,在获取对象的同步锁时,若该同步锁被别的线程占用,则会进入阻塞状态
(3)其他阻塞:运行的线程执行sleep()方法或join()方法,或发出I/O请求,则线程进入阻塞状态
5.死亡状态:线程正常执行结束或者遇到异常,线程或进入死亡状态,*线程不可以再次启动*;
4、实现多线程的方法- 继承Thread类,重写run方法 创建线程对象,调用start方法启动线程
- 实现Runnable接口 重写run方法 创建线程对象,调用start方法启动线程
- 实现Callable接口
线程安全是指在多线程环境下,程序可以始终执行正确的行为,符合预期的逻辑。
-
原子性:一个或者多个操作在 CPU 执行的过程中被中断
- 针对问题1:JDK里面提供了很多atomic类,比如AtomicInteger, AtomicLong, AtomicBoolean等等,这些类本身可以通过CAS来保证操作的原子性;另外Java也提供了各种锁机制,来保证锁内的代码块在同一时刻只能有一个线程执行,比如刚刚的例子我们就可以加锁,如下:
-
可见性:一个线程对共享变量的修改,另外一个线程不能立刻看到
- 同样可以通过synchronized关键字加锁来解决。与此同时,java还提供了一种轻量级的锁,即volatile关键字,要优于synchronized的性能,同样可以保证修改对其他线程的可见性。volatile一般用于对变量的写操作不依赖于当前值的场景中,比如状态标记量等。
-
有序性:程序执行的顺序没有按照代码的先后顺序执行
- 可以通过synchronized关键字定义同步代码块或者同步方法保障有序性,另外也可以通过Lock接口保障有序性。
https://www.cnblogs.com/dolphin0520/p/3920373.html
7、 int和Integer的区别1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值 。
4、Integer的默认值是null,int的默认值是0
8、数组有没有length()方法?String有没有length()方法?答:数组没有length()方法,有length 的属性。String 有length()方法。Javascript中,获得字符串的长度是通过length属性得到的,这一点容易和Java混淆。
9、什么是事务的四个特性? 事务,一般是指要做的或所做的事情。而且事务是应用程序中一系列严密的操作,所有操作必须
成功完成,否则在每个操作中所作的所有更改都会被撤消。
另外,务应该具有4个属性:原子性、一致性、 隔离性、持久性。
- 原子性。一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性。事务执行前后,数据完整性保持一致。一致性与原子性是密切相
关的。 - 隔离性。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据,对并发的
其他事务是隔离的,并发执行的各个事务之间不能互相干扰。 - 持久性。持久性也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性
的。接下来的其他操作或故障不应该对其有任何影响。10、数据库隔离的四个级别分别是什么
数据库隔离的四个级别分别为:
- Read Uncommitted(读取未提交内容)
在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
- Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
- Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
- Serializable(可串行化)
这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
隔离级别所产生的问题
这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
1、脏读(Drity Read):
一个事务读取到另一个事务还未提交的数据
2、不可重复读(Non-repeatable read):
在一个事务中多次读取同一个数据时,结果出现不一致
在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
3、幻读(Phantom Read):
在一个事务中使用相同的 SQL 两次读取,第二次读取到了其他事务新插入的行。
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
在MySQL中,实现了这四种隔离级别,分别有可能产生问题如下所示:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 读未提交 | √ | √ | √ |
| 读已提交 | X | √ | √ |
| 可重复读 | X | X | √ |
| 可串行化 | X | X | X |
| 引擎 | 特性 |
|---|---|
| MYISAM | 不支持事务,不支持外键,支持表锁,支持索引,适合用于频繁查询的应用,插入数据时,锁定整个表,查表总行数时,不需要全表扫描 |
| INNODB | 支持事务,支持外键,支持行锁,不支持全文索引,多应用于插入和更新操作,适合大数据、高并发,查表总行数时,全表扫描 |
- 索引最大的好处是提高查询速度,
- 缺点是更新数据时效率低,因为要同时更新索引
- 对数据进行频繁查询进建立索引,如果要频繁更改数据不建议使用索引。
一、是主索引的区别,InnoDB的数据文件本身就是索引文件。而MyISAM的索引和数据是分开的。
二、是辅助索引的区别:InnoDB的辅助索引data域存储相应记录
| 级别 | 概念 |
|---|---|
| 1NF | 属性不可分 |
| 2NF | 非主键属性,完全依赖于主键属性 |
| 3NF | 非主键属性之间不存在传递依赖 |
a. 设计良好的数据库结构,允许部分数据冗余,尽量避免join查询,提高效率。
b. 选择合适的表字段数据类型和存储引擎,适当的添加索引。
c. mysql库主从读写分离。
d. 找规律分表,减少单表中的数据量提高查询速度。
e。添加缓存机制,比如memcached,apc等。
f. 不经常改动的页面,生成静态页面。
g. 书写高效率的SQL。比如 SELECT * FROM TABEL 改为 SELECt field_1, field_2, field_3 FROM TABLE
1、选择正确的存储引擎
InnoDB适合于大量的写操作且支持事务操作
MyISAM适合于一些需要大量查询的应用,不支持事务
2、优化字段的数据类型
记住一个原则,越小的列会越快。如果一个表只会有几列罢了(比如说字典表,配置表),那么,我们就没有理由使用 INT 来做主键,使用 MEDIUMINT, SMALLINT 或是更小的 TINYINT 会更经济一些。如果你不需要记录时间,使用 DATE 要比 DATETIME 好得多。当然,你也需要留够足够的扩展空间
3、为搜索字段添加索引
索引并不一定就是给主键或是唯一的字段。如果在你的表中,有某个字段你总要会经常用来做搜索,那么最好是为其建立索引,除非你要搜索的字段是大的文本字段,那应该建立全文索引
4、避免使用Select * (使用高效的Sql语句)
从数据库里读出越多的数据,那么查询就会变得越慢。并且,如果你的数据库服务器和WEB服务器是两台独立的服务器的话,这还会增加网络传输的负载。即使你要查询数据表的所有字段,也尽量不要用*通配符,善用内置提供的字段排除定义也许能给带来更多的便利
5、使用 ENUM 而不是 VARCHAR
ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。例如,性别、民族、部门和状态之类的这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR
6、尽可能的使用 NOT NULL
除非你有一个很特别的原因去使用 NULL 值,你应该总是让你的字段保持 NOT NULL。 NULL其实需要额外的空间,并且,在你进行比较的时候,你的程序会更复杂。 当然,这里并不是说你就不能使用NULL了,现实情况是很复杂的,依然会有些情况下,你需要使用NULL值
7、固定长度的表会更快
如果表中的所有字段都是“固定长度”的,整个表会被认为是 “static” 或 “fixed-length”。 例如,表中没有如下类型的字段: VARCHAR,TEXT,BLOB。只要你包括了其中一个这些字段,那么这个表就不是“固定长度静态表”了,这样,MySQL 引擎会用另一种方法来处理
固定长度的表会提高性能,因为MySQL搜寻得会更快一些,因为这些固定的长度是很容易计算下一个数据的偏移量的,所以读取的自然也会很快。而如果字段不是定长的,那么,每一次要找下一条的话,需要程序找到主键
并且,固定长度的表也更容易被缓存和重建。不过,唯一的副作用是,固定长度的字段会浪费一些空间,因为定长的字段无论你用不用,他都是要分配那么多的空间
① 读写分离
② 分段加锁
③ 减少锁持有的时间
④ 多个线程尽量以相同的顺序去获取资源
这些都不是绝对原则,都要根据情况,比如不能将锁的细粒度过于细化,不然可能会出现线程的加锁和释放次数过多,反而效率不如一次加一把大锁
死锁的四个必要条件:
-
互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,
只能等待,直至占有该资源的进程使用完成后释放该资源
-
请求和保持条件:进程获得一 定的资源之后,又对其他资源发出请求,但是该资源
可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放 -
不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在
使用完后自己释放 -
环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待
资源关系



