请教我kao代码

Knowledge gives us ways to survive the destruction until the rebirth arrives

0%

简介

是什么

​ 动态代理通过反射实现,是OOP(面向对象编程)的延伸。

​ 可以对业务逻辑的各个部分进行隔离,从而实现解耦合。

作用及优势

​ 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强

​ 优势:减少重复代码,提高开发效率,并且便于维护

​ 对单一功能进行增强,附加其它功能的思维。例如对于user的操作,不需要在每一个功能中

​ 写上日志控制功能,只需要在运行时将额外的日志控制功能附加到当前所运行功能上就可以了。从而实现了解耦。

阅读全文 »

前言

ssm: mybatis + spring + springMVC

ssm = JavaWeb做项目

Spring:IOC和AOP【重要】

SpringMVC的执行流程【重要】

回顾MVC模式

模型(dao,service) 视图(jsp) 控制器(servlet)

jsp:本质就是一个servlet

什么是SpringMVC

Spring MVC是Spring Framework的一部分,是基于java实现MVC的轻量级Web框架。

阅读全文 »

悲观锁

当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制【Pessimistic Concurrency Control,缩写“PCC”,又名“悲观锁”】。

之所以叫做悲观锁,是因为这是一种对数据的修改持有悲观态度的并发控制方式。总是假设最坏的情况,每次读取数据的时候都默认其他线程会更改数据,因此需要进行加锁操作,当其他线程想要访问数据时,都需要阻塞挂起。悲观锁的实现:

  1. 传统的关系型数据库使用这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
  2. Java 里面的同步 synchronized]关键字的实现。

悲观锁分为共享(读)锁和排他(写)锁

共享锁【shared locks】又称为读锁,简称S锁。顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

排他锁【exclusive locks】又称为写锁,简称X锁。顾名思义,排他锁就是不能与其他锁并存,如果一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据行读取和修改。

乐观锁

阅读全文 »

什么是操作系统

  1. 操作系统是管理计算机软硬件资源的程序,是计算机的基石。

  2. 本质上是一个应用程序。

  3. 操作系统的存在屏蔽了硬件设备的复杂性,由操作系统统一管理和分配。

  4. 内核是操作系统的核心部分。负责系统的内存管理,硬件设备管理,文件系统管理和应用程序管理。

什么是系统调用

用户态:该状态运行的进程可以直接读取用户程序的数据。

系统态:该状态运行的进程或程序可以访问计算机任意资源。

程序运行在用户态时想要调用操作系统提供的系统态子功能时需要进行系统调用。

系统调用按功能大致分为:

设备管理。完成设备的请求或释放,以及设备启动等功能。

⽂件管理。完成⽂件的读、写、创建及删除等功能。

进程控制。完成进程的创建、撤销、阻塞及唤醒等功能。

阅读全文 »

数据库索引的原理:数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现通常使用 BTree 及其变种 B+Tree。

一般情况下,在没有建立索引的时候, mysql 需要扫描全表及扫描 10W 条数据找这条数据,如果我在 nickname 上建立索引,那么mysql只需要扫描一行数据及为我们找到这条 nickname='css' 的数据,是不是感觉性能提升了好多咧....

mysql 的索引分为 单例索引(主键索引、唯一索引、普通索引)和 组合索引。

  • 单例索引:一个索引只包含一个列,一个表可以有多个单例索引。
  • 组合索引:一个组合索引包含两个或两个以上的列。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CREATE TABLE `award` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`aty_id` varchar(100) NOT NULL DEFAULT '' COMMENT '活动场景id',
`nickname` varchar(12) NOT NULL DEFAULT '' COMMENT '用户昵称',
`is_awarded` tinyint(1) NOT NULL DEFAULT 0 COMMENT '用户是否领奖',
`award_time` int(11) NOT NULL DEFAULT 0 COMMENT '领奖时间',
`account` varchar(12) NOT NULL DEFAULT '' COMMENT '帐号',
`password` char(32) NOT NULL DEFAULT '' COMMENT '密码',
`message` varchar(255) NOT NULL DEFAULT '' COMMENT '获奖信息',
`created_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
`updated_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='获奖信息表';

INSERT INTO `award` (`nickname`, `account`, `message`, `created_time`)
VALUES ('rSUQFzpkDz3R', 'DYxJoqZq2rd7', 'aaabbbccccxuxuxuxuuxux', 1449567822);

索引的创建

单例索引

  1. 普通索引

是最基本的索引。

阅读全文 »

基本概念

  1. 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

    (1)同步阻塞IO(Blocking IO):即传统的IO模型。

    (2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。

    (3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。

    (4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

    同步和异步的概念描述的是用户线程与内核的交互方式:同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;而异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

    阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:阻塞是指IO操作需要彻底完成后才返回到用户空间;而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

同步阻塞

同步阻塞IO模型是最简单的IO模型,用户线程在内核进行IO操作时被阻塞。

同步非阻塞IO

同步非阻塞IO是在同步阻塞IO的基础上,将socket设置为NONBLOCK。这样做用户线程可以在发起IO请求后可以立即返回。

整个IO请求的过程中,虽然用户线程每次发起IO请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。

阅读全文 »

单例模式是什么?

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式实现方式

饿汉式

类加载的时候就创建了实例 优点:类加载的时候创建一次实例,避免了多线程同步问题

缺点:即使单例没被用到也会创建,浪费内存

1
2
3
4
5
6
7
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return instance;
}
}

懒汉式

阅读全文 »

根据“类是否覆盖equals()方法”,将它分为2类。

  1. 若某个类没有覆盖equals()方法,当它的通过equals()比较两个对象时,实际上是比较两个对象是不是同一个对象。这时,等价于通过“==”去比较这两个对象。

  2. 我们可以覆盖类的equals()方法,来让equals()通过其它方式比较两个对象是否相等。通常的做法是:若两个对象的内容相等,则equals()方法返回true;否则,返回fasle。

“hashCode() 和 equals() ”是有关系的:

​ 1)、如果两个对象相等,那么它们的hashCode()值一定相同。

​ 这里的相等是指,通过equals()比较两个对象时返回true。

​ 2)、如果两个对象hashCode()相等,它们并不一定相等。

​ 因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等

参考代码 (ConflictHashCodeTest1.java):

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
1 import java.util.*;
2 import java.lang.Comparable;
3
4 /**
5 * @desc 比较equals() 返回true 以及 返回false时, hashCode()的值。
6 *
7 * @author skywang
8 * @emai kuiwu-wang@163.com
9 */
10 public class ConflictHashCodeTest1{
11
12 public static void main(String[] args) {
13 // 新建Person对象,
14 Person p1 = new Person("eee", 100);
15 Person p2 = new Person("eee", 100);
16 Person p3 = new Person("aaa", 200);
17
18 // 新建HashSet对象
19 HashSet set = new HashSet();
20 set.add(p1);
21 set.add(p2);
22 set.add(p3);
23
24 // 比较p1 和 p2, 并打印它们的hashCode()
25 System.out.printf("p1.equals(p2) : %s; p1(%d) p2(%d)\n", p1.equals(p2), p1.hashCode(), p2.hashCode());
26 // 打印set
27 System.out.printf("set:%s\n", set);
28 }
29
30 /**
31 * @desc Person类。
32 */
33 private static class Person {
34 int age;
35 String name;
36
37 public Person(String name, int age) {
38 this.name = name;
39 this.age = age;
40 }
41
42 public String toString() {
43 return "("+name + ", " +age+")";
44 }
45
46 /**
47 * @desc 覆盖equals方法
48 */
49 @Override
50 public boolean equals(Object obj){
51 if(obj == null){
52 return false;
53 }
54
55 //如果是同一个对象返回true,反之返回false
56 if(this == obj){
57 return true;
58 }
59
60 //判断是否类型相同
61 if(this.getClass() != obj.getClass()){
62 return false;
63 }
64
65 Person person = (Person)obj;
66 return name.equals(person.name) && age==person.age;
67 }
68 }
69 }

复制代码

阅读全文 »

摘要

分类

  1. 性能分析

实现

插入排序

直接插入排序

直接插入排序的核心思想就是:将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小,则交换,直到全部元素都比较过。 因此,从上面的描述中我们可以发现,直接插入排序可以用两个循环完成:

阅读全文 »

HashMap线程不安全

HashMap在扩容的时候会调用resize()方法,这样的并发操作容易在一个桶上形成环形链表。当获取一个不存在的key时,计算出的index正好时环形链表的下标时就会出现如下的死循环。

ConcurrentHashMap线程安全

引入了如下的Segment数组

其中的核心数据,例如value和链表都是由volatile修饰的,保证了数据的可见性。

原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。

jdk1.8抛弃了原有的segment锁,而使用CAS(Compare ans Swap) + synchronized的方式实现。

阅读全文 »