0%

文章字数:208,阅读全文大约需要1分钟
参数|抽象类|接口
:—|:—|:—
默认方法实现|都可以有默认方法实现|defaultstatic方法可以有默认实现
实现|子类使用extends关键字继承抽象类,如果子类不是抽象类,则必须实现所有抽象方法|使用implements实现接口,需要实现除了default之外的接口
构造器|可以有|不能有
与正常类区别|除了不能实例化,其它没区别|完全两种类型
访问修饰符|publicprotecteddefault|只能是public可省略
main方法|可以有,并能运行|staticdefault可以在main中使用功能
继承|继承一个类和多个接口|可以继承一个或多个接口
速度|速度快,因为单继承|需要找实现类中的实现方法,稍慢


文章字数:23,阅读全文大约需要1分钟

1
2
3
4
5
// 创建元素,设置地址
var script = document.createElement('script');
script.src = "https://xxxxx.js";
// 添加到head标签中
document.getElementsByTagName('head')[0].appendChild(script);

文章字数:494,阅读全文大约需要1分钟

优化方式

  • 表结构设计合理3NF
  • 添加索引普通索引 主键索引 唯一索引unique 全文索引
  • sql语句优化
  • 分表技术水平分割 垂直分割
  • 读写分离
  • 配置优化,配置最大并发,缓存

定位需要优化点(慢查询日志)

MySQL中日志有:错误日志二进制日志通用查询日志慢查询日志

  • 二进制日志通过监听此日志建立主从结构
  • 通用查询建立客户端连接和执行的语句
  • 慢查询所有执行时间超过long_query_time秒的所有查询或者不适用所用的查询
    配置慢查询
    1
    2
    3
    4
    5
    6
    7
    1.my.ini中增加
    long_query_time=2

    2.可在直接在mysql连接中开启
    set global slow_query_log=ON
    set global long_query_time = 3600;
    set global log_querise_not_using_indexes = ON;

语句分析

  • explain关键字,显示了mysql如何使用索引处理查询及表连接
    1
    EXPLAIN SELECT * FROM USER ORDER BY TIME LIMIT 0,100
    结果中常用的信息:
列名 含义
id select查询序列号
select_type 查询类型(union相关)
table 那张表
type 使用了何种类型,从好到坏:const、eq_reg、ref、range、index、ALL
- const:表最多有一个匹配行
- eq_ref:对于多表行组合,从改表中只读取一行
- ref:对于每个来自前面表的行组合,所有匹配索引值的行都从这张表中读取
- ref_or_null:该联接类型如同ref,但是添加了MySQL可以专门所有包含NULL值的行。
- index_merge:该联接类型表示使用了索引合并优化
- unique_subquery:索引查找含糊,替固定代子查询,效率更高
- index_subquery:改联接类型类似于unique_subquery
- range:只检索给定范围的行,使用一个索引来选择行
- index:该联接类型与ALL相同,除了只有索引树被扫描。扫描索引比扫描数据文件块一点
- ALL:对于每个来自前面的表的行组合,完整扫描了表数据

文章字数:175,阅读全文大约需要1分钟

插入排序就是将数据依次和左边的数据比较,直到有一个位置是它存在的区间(大于左边的,小于右边的)。就插入,并开始下一个。直到全部插入左边。即右边按顺序取出数据放到左边合适的地方

时间复杂度 o(n) - o(n^2)
因为找到合适的位置就不再对比了,所以最好的情况是已经拍好,即每个都对比一次O(n)。最不好的情况是反向排序,每个都要对比O(n^2)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void sort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; ++i) {
int value = arr[i];
int j = 0;//插入的位置
for (j = i-1; j >= 0; j--) {
if (arr[j] > value) {
arr[j+1] = arr[j];//移动数据
} else {
break;
}
}
arr[j+1] = value; //插入数据
}
}

文章字数:174,阅读全文大约需要1分钟

堆(heap)又被成为优先队列(priority queue)。堆虽然也是从头部取出元素,从堆底插入,但是堆中的元素排列是按照一定顺序排列的。

两种堆

  1. 最大堆(大顶堆):任意节点必须是起子树的最大值
  2. 最小堆(小顶堆):任意节点必须是起子树的最小值

特征

  1. 维持完全二叉树
  2. 子类数字总是大于父类数字

支持的操作

  1. 添加
  2. 删除
  3. 查找最大/最小值

堆排序

  1. 将数据存入堆
  2. 挨个取出(取出的一定是最大值)
    就排列好了。

文章字数:593,阅读全文大约需要2分钟

数据库隔离级别是只多个并行的事务之间的锁策略

隔离级别

等级 名称 说明 产生的问题
0 Read Uncommitted 读未提交,即并行的事务中没有提交的数据其它事务也可以查询的到 脏读(读取到别的事务回滚前的脏数据)、不可重复读(一个事务多次读取的数据不一样)、幻读(一个事务多次读取的数据条数不一样)
1 READ COMMITTED 读提交,不会读到其它事务没提交的数据 不可重复读(一个事务多次读取的数据不一样)、幻读(一个事务多次读取的数据条数不一样)
2 REPEATABLE READ 重复读,不能修改其它事务已读取但为提交的数据 幻读(一个事务多次读取的数据条数不一样)、性能损失
3 Serializable 串行化,事务间串行执行 不存在并行的事务,所以没问题

问题分析

  1. 脏读:读到别的事务还没回滚前的脏数据,只有读未提交下允许读其他事务没提交的数据,所以只有读未提交才会有
  2. 不可重复读:并行的事务将数据更改了,导致另一个事物两次读一条数据的结果都不一样。即不能保证两次读取数据相同,即不可重复读。重复读禁止事务修改被其它事务读的数据,所以避免此问题。(针对update、delete)
  3. 幻读:和不可重复读类似,但是被改变的是匹配查询语句的数据条数。第一次读匹配一条,被另一个并行事务修改后又读到了两条。此为幻读。幻读并不是改变已经读到的数据,而是增加条目,所以只有串行化可以解决(针对insert)

文章字数:51,阅读全文大约需要1分钟
强制不换行:

1
p { white-space:nowrap; }

自动换行:

1
p { word-wrap:break-word; }

强制英文单词断行:

1
p { word-break:break-all; }

注意:设置强制将英文单词断行,需要将行内元素设置为块级元素。


文章字数:247,阅读全文大约需要1分钟

获取给定的字符串的不重复的最长子串的长度。

滑动窗口法

滑动窗口法是常用的字符操作算法

  1. 设定一个窗口,窗口的开端对应着数组的开关
  2. 窗口向后扩展,直到扩展到一个有重复数据
  3. 窗口的前部向后移动,到重复的元素后面。
  4. 继续延伸。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.util.HashMap;
import java.util.Map;

public class Solution {
public static int lengthOfLongestSubstring(String s) {
int maxLength = 0;
Map<Character, Integer> window = new HashMap();
// 0. 滑动窗口法
// 1. i 不变,j一直向后
// 2. j和i重复时 i移动到第一个重复的元素之后。(如果重复的元素在i之前就不变)
for (int i = 0, j = 0; j < s.length(); j++) {
if (window.containsKey(s.charAt(j))) {
// 防止i变小, 如 abba 的情况
i = Math.max(window.get(s.charAt(j)) + 1, i);
}
window.put(s.charAt(j), j);
int length = j - i + 1;
maxLength = Math.max(maxLength, length);
}
return maxLength;
}

public static void main(String[] args) {
System.out.println("lengthOfLongestSubstring(\"abba\") = " + lengthOfLongestSubstring("abba"));
}
}

文章字数:372,阅读全文大约需要1分钟

Lock接口是语言层面的锁

一、 常用方法

  • lock()加锁
  • lockInterruptibly()可中断获取锁的过程
  • unlock()释放锁
  • tryLock()尝试获取锁
  • tryLock(long, TimeUnit)可设置获取锁超时

二、对比synchronized

  • 不可中断
  • 不可超时
  • synchronized更简洁
  • 需要锁中断、超时、尝试的时候使用Lock锁,其他尽量使用synchronized

三、可重入锁

  • synchronized是隐式可重入锁
  • ReentrantLockLock的可重入锁实现类,相当于synchronized的代码层实现

四、公平和非公平锁

  • 公平锁,先获取先执行。
  • 非公平锁,新来的执行。效率高,取消了新来的锁的状态切换过程,直接执行。
  • ReentrantLock(true)公平锁
  • ReentrantLock()默认是非公平锁

五、读写锁

  • 排它锁,synchronizedReentrantLock都是排它锁,只允许一个线程获取数据。
  • 读写锁,维护读和写两个锁。适用于读多写少的操作。
  • ReadWriteLock接口下的ReentrantReadWriteLock
  • getlock = readWriteLock.readLock()获取读锁,getlock.lock()
  • setlock = readWriteLock.writeLock()获取写锁,getlock.lock()
    锁的一般用法
    1
    2
    3
    4
    5
    6
    lock.lock();
    try{
    //...
    } finally {
    lock.unlock();
    }

六、Condition接口

  • 实现线程唤醒(通知)功能
  • 每个锁的实现都有getCondition方法可以获取,一个锁可以多个

6.1使用

1
2
3
4
5
6
7
lock.lock();
try{
//...
cond.signal();// 唤醒,因为和等待线程是一一对于的,所以不用All
} finally {
lock.unlock();
}
1
2
3
4
5
6
7
8
9
10
lock.lock();
try{
try{
cond.await();//等待唤醒
}catch(InterruptedException e) {
e.printStackTrace();
}
} finally {
lock.unlock();
}

文章字数:64,阅读全文大约需要1分钟

很多框架的源码里都有使用到assert,这里学习一下

开启断言

默认关闭

  • jvm加上参数-ea或者-enableassertions

使用

如果判断语句为false,则会报错,并提示指定信息。

1
assert a > 0 : "error message";