MySQL数据库:索引
索引是一种用于快速查找和检索数据的数据结构,类似于图书的目录,通过索引可以更快地找到对应的数据。
索引的优缺点
优点:
提高了查找的效率
通过创建唯一性索引,确保了每一行数据的唯一性。
缺点:
索引使用物理文件存储,带来了空间的消耗。
创建和维护索引需要耗费时间。当数据发生更改时,索引也会动态修改,降低SQL执行效率。
索引SQL
查看索引
1show 索引名 from 表名(列名);
创建索引
1create index 索引名 on 表名(列名);
删除索引
1drop index 索引名 on 表名
索引底层的数据结构
索引是一种查找更快的数据结果。
数组和链表的查找都需要遍历,最先淘汰。
二叉搜索树最坏情况下会变成单支树,查找的时间复杂度变为O(N),淘汰。
AVL树和红黑树使得左右子树高度相对平衡,但数据量太大时,树的高度过高,比较次数过多,即磁盘IO过多,淘汰。
哈希表查找的时间复杂度是O(1),是不是可以作为索引的数据结构了呢?NO!哈希表不支持顺序和范围查找,而SQL要经常进行排序和
范围查询,淘汰。
目前大多数数据库采用B树或B+树作为索引结构,在MyS ...
socket套接字网络编程
网络编程使计算机不再是一个孤立的个体,而是一个互联的整体,通过网络编程,可实现主机各进程间的数据传输。网络编程的核心就是套接字socket。socket是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。
socket主要分为三类:流套接字、数据报套接字、原始套接字。我们这里主要介绍前两种:
流套接字:使用传输层TCP协议,提供面向连接、可靠的数据传输,面向字节流,有接收缓冲区和发送缓冲区,传输数据大小无限制。
数据报套接字:使用传输层UDP协议,提供无连接、不可靠传输,面向数据报,只有接收缓冲区,传输大小受限,一次最多传输64K。
下面我们来看下Java中是如何使用socket来进行网络编程的。
数据报套接字
Java数据报套接字编程有两个核心的类,DatagramSocket和DatagramPacket。
两个核心类
DatagramSocket用于创建一个数据报套接字,用于发送和接收数据报。主要的构造方法如下:
方法名
说明
DatagramSocket()
创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口 (一般用 ...
Java文件和IO流
文件基础操作
1234567891011121314151617181920public static void main(String[] args) throws IOException { //创建一个hello的目录 File dir = new File("hello"); if(!dir.exists()){ dir.mkdirs(); } //在hello目录下创建一个hello.txt文件 File file = new File(dir+"/hello.txt"); if(!file.exists()){ file.createNewFile(); } //得到文件名 System.out.println(file.getName()); //得到文件的绝对路径 System.out.println(file.getAbsolutePath()); //得到文件的规范路径,当 ...
多线程实例:线程池
顾名思义,线程池就是存放线程的池子。直接用线程不就好了吗,为什么还需要线程池呢?
相比进程,线程已经轻量很多了,创建和销毁线程消耗的资源会少很多,但终究还是有消耗的。为了进一步降低消耗,我们需要用到线程池。需要用到线程时不用申请,直接从线程池中取,用完之后也不用销毁,再放进线程池。
标准库中的线程池(简化版本):
123456789public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(new Runnable() { @Override public void run() { System.out.println("hello"); } });}
模拟实现一个简化版本的线程池:
描述任务:直接用Runnable接口即可
组织任务:用到阻塞队列
描述工作线程:创建 ...
多线程实例:定时器
定时器是实际开发中常用的组件,例如文章的定时发布,双11的准点抢购活动等。
下面我们来看一下Java标准库中的定时器。
123456789public static void main(String[] args) { Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("hello"); } }, 3000);}
该定时器会在3秒之后输出“hello”。创建一个定时器需要用到Timer类中的核心方法schedule,该方法内有两个参数,一个表示要执行的任务,一个表示任务在多长时间后执行。
认识了标准库中的定时器后,我们可以自己来模拟实现一个定时器。
首先,描述一个任务。创建一个MyTask类,类中有两个属性:一个是执行的任务,一个是任务执行时间。这两个属性类似于 ...
多线程实例:阻塞队列
阻塞队列是一种具有阻塞功能的队列,满足队列“先进先出”的特点,是一种线性安全的数据结构。当队列为空时,执行出队操作会进行阻塞,直到队列中有元素为止;当队列已经满了,执行入堆操作会进行阻塞,知道队列有空间为止。
阻塞队列的一个典型应用常见就是“生产者消费者”模型。毫无疑问,该模型有两个主体:生产者和消费者。生产者线程负责生产产品,将生产好的产品放进阻塞队列。消费者线程负责消费产品,直接从阻塞队列取产品。
生产者消费者模型具有解耦、平衡速度差异的特点。
解耦:生产者无需关注是谁在消费产品,消费了多少产品,只需关注生产操作即可;消费者无需关注是谁在生产产品,生产了多少产品,只需关注消费操作即可。
平衡速度差异:设想11.11,大量用户向服务器发送了大量的支付请求,一次性将这些请求交给服务器处理,服务器可能会hole不住,因此将这些请求都放进阻塞队列,消费者线程从阻塞队列一个一个地来处理请求就好了。这样就起到了“削峰填谷”的作用,平衡了生产者和消费者之间的速度差异。
标准库中的阻塞队列:
123456public static void main(String[] args) throws I ...
Java线程的创建及状态
什么是线程
在计算机中,一个任务就是一个进程。打开任务管理器,我们可以看见多个进程。如浏览器,QQ。线程是进程的再划分,是进程的一部分。一个进程可以只有一个线程(主线程),也可以有多个线程。拿浏览器举例,打开浏览器的多个网页,一个网页在播放音乐,一个网页在播放视频,一个网页在浏览博客。每个网页有不同的分工,这些浏览器的每个子任务就是一个线程。
线程是更轻量的进程,创建一个线程的消耗要低于创建一个进程,且同一进程的不同线程之间可以共享资源,效率更高。通过多线程可以更好地实现并发编程。
进程vs线程
进程包含线程,进程是线程的一部分,一个进程中至少包含一个线程。
进程与进程之间不能共享资源,同一个进程的线程之间可以共享资源。
进程是系统分配资源的最小单位,线程是系统调度执行的最小单位。
多进程稳定性高于多线程,一个进程的崩溃不会影响其他线程;多线程下一个线程的崩溃可能影响该进程。
创建线程
一个线程至少包含一个进程,main()就是一个线程,我们还可以在里面创建多个线程。
1.继承Thread类,重写run()方法
12345678910111213public class Main ...
线程安全及解决方案
安全,已经成为非常重要的社会话题。所谓“安全第一”,“安全无小事”(手动滑稽),同样,多线程中,线程安全也是非常重要的话题。那么是什么原因造成了线程不安全,又如何解决线程不安全呢?
造成线程不安全的原因
线程的调度
各线程之间是抢占式执行的,线程的执行顺序是随机的,因此可能会产生各种问题。现在最流行什么?做核酸!如果做核酸是抢占式的,做核酸没有一个顺序,做核酸顺序完全靠运气,这能安全吗!
多线程同时修改同一变量
如果是多线程同时读取同一变量,不涉及修改的操作,是线程安全的。但如果多线程同时修改同一变量,这能不乱吗?想当年家里买了一台电脑,我姐姐要用电脑玩QQ炫舞,我要用电脑玩穿越火线,你争我抢,打的是不可开交。
操作指令不是原子的
例如一条加法指令,其实要执行三条指令,load、add、save,先将内存中的变量加载到寄存器,在寄存器中完成加法操作,再将结果写会内存中。假设线程1完成了load、add操作,线程2完成了load、add、save操作,当线程1再去执行save操作,便将线程2的操作覆盖了,线程2说:线程1真是一个猪队友。
内存可见性
线程1循环进行读操作, ...
Java单例模式:懒汉模式和饿汉模式
单例模式,就是一个类中只有一个实例。主要有懒汉模式和饿汉模式。
饿汉模式是在类加载的同时就创建实例,而懒汉模式是使用时才创建实例。
饿汉模式
12345678910class Singleton{ //1.使用static创建一个实例,并且立即实例化 private static Singleton instance = new Singleton(); //2.为了防止在其他地方不小心new这个Singleton,把方法构造为private private Singleton(){} //3.提供一个方法,让外面能够拿到唯一实例 public static Singleton getInstance() { return instance; }}
在多线程中,多个线程对同一数据进行读操作,线程安全。
懒汉模式
12345678910111213class Singleton{ //1.不立即初始化实例,使用时再初始化 private static ...
【JavaWeb】Thymeleaf模板引擎
上篇博客中,我们了解了服务器渲染,并用Thymeleaf模板引擎写了一个简单的猜数字小游戏。
下面我们简单了解一下Thymeleaf的语法。
Thymeleaf常见命令
命令
功能
th:text
在标签体中展示表达式求值结果的文本内容
th:[HTML标签属性]
设置任意的 HTML 标签属性的值
th:if
当表达式的结果为真时则显示内容,否则不显示
th:each
循环访问元素
Thymeleaf语法有很多,我们这里先简单介绍这四个。th:text和th:if在猜数字小游戏案例已经使用过,这里不再介绍。
th:[属性]
HTML模板代码:
1234<body> <a th:href="${url1}">胖虎同学</a> <a th:href="${url2}">胖虎同学1</a></body>
Servlet代码:
12345678910111213141516171819202 ...