知识梳理(五)

目录

一、多线程

1.线程与进程

2.并发与并行

3.程序运行原理

4.创建线程的方式

5.线程生命周期图

6.线程池

7.线程安全

8.等待唤醒机制

二、网络编程

1.网络通信协议

2UDP协议

3.TCP协议

4.UDP程序交互流程

5.TCP程序交互流程

三、数据库表常用指令

四、数据库表的相关操作

五、数据库表中的数据操作


一、多线程

1.线程与进程

        线程是程序中⼀个单⼀的顺序控制流程。进程内有⼀个相对独⽴的、可调度的执⾏单元,是系统独⽴调 度和分派CPU的基本单位指令运⾏时的程序的调度单位。在单个程序中同时运⾏多个线程完成不同的⼯ 作,称为多线程。

         进程:进程指正在运⾏的程序。确切的来说,当⼀个程序进⼊内存运⾏,即变成⼀个进程,进程是处于 运⾏过程中的程序,并且具有⼀定独⽴功能。

JVM的启动是多线程的吗?

JVM启动⾄少启动了垃圾回收线程和主线程,所以是多线程的。

2.并发与并行

并发: 是当有多个线程在操作时,如果系统只有⼀个CPU,则它根本不可能真正同时进⾏⼀个以上的线程, 它只能把CPU运⾏时间划分成若⼲个时间段,再将时间段分配给各个线程执⾏,在⼀个时间段的线程代 码运⾏时,其它线程处于挂起状。这种⽅式我们称之为并发(Concurrent)。 如果⽤⼀台电脑我先给甲发个消息,然后⽴刻再给⼄发消息,然后再跟甲聊,再跟⼄聊。这就叫并发。

并⾏: 当系统有⼀个以上CPU时,则线程的操作有可能⾮并发。当⼀个CPU执⾏⼀个线程时,另⼀个CPU可 以执⾏另⼀个线程,两个线程互不抢占CPU资源,可以同时进⾏,这种⽅式我们称之为并 ⾏(Parallel)。 ⽐如我跟两个⽹友聊天,左⼿操作⼀个电脑跟甲聊,同时右⼿⽤另⼀台电脑跟⼄聊天,这就叫并 ⾏。

区别: 并发和并⾏是即相似⼜有区别的两个概念, 并⾏是指两个或者多个事件在同⼀时刻发⽣; ⽽并发是指两个或多个事件在同⼀时间间隔内发⽣。

3.程序运行原理

1.分时调度

        所有线程轮流使⽤ CPU 的使⽤权,平均分配每个线程占⽤ CPU 的时间。

2.抢占式调度

        优先让优先级⾼的线程使⽤ CPU,如果线程的优先级相同,那么会随机选择⼀个(线程随机性),Java 使⽤的为抢占式调度。

3.抢占式调度详解

        ⼤部分操作系统都⽀持多进程并发运⾏,现在的操作系统⼏乎都⽀持同时运⾏多个程序。⽐如:现在我 们上课⼀边使⽤编辑器,⼀边使⽤录屏软件,同时还开着画图板,dos窗⼝等软件。此时,这些程序是 在同时运⾏,"感觉这些软件好像在同⼀时刻运⾏着"。 实际上,CPU(*处理器)使⽤抢占式调度模式在多个线程间进⾏着⾼速的切换。对于CPU的⼀个核⽽ ⾔,某个时刻,只能执⾏⼀个线程,⽽ CPU的在多个线程间切换速度相对我们的感觉要快,看上去就 是在同⼀时刻运⾏。 其实,多线程程序并不能提⾼程序的运⾏速度,但能够提⾼程序运⾏效率,让CPU的使⽤率更⾼。

4.创建线程的方式

⽅式1,继承Thread线程类

步骤

1, ⾃定义类继承Thread类

2, 在⾃定义类中重写Thread类的run⽅法

3, 创建⾃定义类对象(线程对象)

4, 调⽤start⽅法,启动线程,通过JVM,调⽤线程中的run⽅法

⽅式2,实现Runnable接⼝

步骤

1, 创建线程任务类 实现Runnable接⼝

2, 在线程任务类中 重写接⼝中的run⽅法

3, 创建线程任务类对象

4, 创建线程对象,把线程任务类对象作为Thread类构造⽅法的参数使⽤

5, 调⽤start⽅法,启动线程,通过JVM,调⽤线程任务类中的run⽅法

5.线程生命周期图

知识梳理(五)

6.线程池

        在java中,如果每个请求到达就创建⼀个新线程,开销是相当⼤的。在实际使⽤中,创建和销毁线程 花费的时间和消耗的系统资源都相当⼤,甚⾄可能要⽐在处理实际的⽤户请求的时间和资源要多的多。 除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在⼀个jvm⾥创建太多的线程,可能会使系统由于过度消耗内存或“切换过度”⽽导致系统资源不⾜。为了防⽌资源不⾜,需要采 取⼀些办法来限制任何给定时刻处理的请求数⽬,尽可能减少创建和销毁线程的次数,特别是⼀些资源 耗费⽐较⼤的线程的创建和销毁,尽量利⽤已有对象来进⾏服务。

         线程池主要⽤来解决线程⽣命周期开销问题和资源不⾜问题。通过对多个任务重复使⽤线程,线程创建 的开销就被分摊到了多个任务上了,⽽且由于在请求到达时线程已经存在,所以消除了线程创建所带来 的延迟。这样,就可以⽴即为请求服务,使⽤应⽤程序响应更快。另外,通过适当的调整线程中的线程 数⽬可以防⽌出现资源不⾜的情况。

【线程池的作⽤?】

1、限定线程的个数,不会导致由于线程过多导致系统运⾏缓慢或崩溃

2、线程池不需要每次都去创建或销毁,节约了资源、

3、线程池不需要每次都去创建,响应时间更快

7.线程安全

//方式1: 同步代码块 -同步代码块的锁对象可以是任意的对象 
    synchronized (锁对象){ 
    可能产生线程安全问题的代码
    }

//方式2: 同步方法-同步方法中的锁对象是 
    this public synchronized void method(){
    可能产生线程安全问题的代码 
    }

//方式3: 静态同步方法- 静态同步方法中的锁对象是 
    类名.class public synchronized void method(){ 
    可能产生线程安全问题的代码 
    }

8.等待唤醒机制

         线程之间的通信:多个线程在处理同一个资源,但是处理的动作 (线程的任务)却不相同。通过一定的手段使各个线程能有效的利用资源。而这种手段即—— 等待唤醒机制。 等待唤醒机制所涉及到的方法:

wait() :等待,将正在执行的线程释放其执行资格 和 执行权,并存储到线程池中。

notify():唤醒,唤醒线程池中被wait()的线程,一次唤醒一个,而且是任意的。

notifyAll(): 唤醒全部:可以将线程池中的所有wait() 线程都唤醒。

        其实,所谓唤醒的意思就是让 线程池中的线程具备执行资格。必须注意的是,这些方法都是在 同步中才有效。同时这 些方法在使用时必须标明所属锁,这样才可以明确出这些方法操作的到底是哪个锁上的线程。

二、网络编程

1.网络通信协议

        ⽹络通信协议有很多种,⽬前应⽤最⼴泛的是TCP/IP协议(Transmission Control Protocol/Internet Protocol传输控制协议/IP协议),它是⼀个包括TCP协议和IP协议, UDP(User Datagram Protocol)协议和其它⼀些协议的协议组,在学习具体协议之前⾸先了解⼀ 下TCP/IP协议组的层次结构。

        在进⾏数据传输时,要求发送的数据与收到的数据完全⼀样,这时,就需要在原有的数据上添加很多信 息,以保证数据在传输过程中数据格式完全⼀致。

TCP/IP协议中的四层分别是应⽤层、传输层、⽹络层和链路层,每层分别负责不同的通信功 能,接下来针对这四层进⾏详细地讲解。 

链路层:链路层是⽤于定义物理传输通道,通常是对某些⽹络连接设备的驱动协议,例如针对光纤、⽹ 线提供的驱动。

⽹络层:⽹络层是整个TCP/IP协议的核⼼,它主要⽤于将传输的数据进⾏分组,将分组数据发送到⽬ 标计算机或者⽹络。

传输层:主要使⽹络程序进⾏通信,在进⾏⽹络通信时,可以采⽤TCP协议,也可以采⽤UDP协议。

应⽤层:主要负责应⽤程序的协议,例如HTTP协议、FTP协议等。

2UDP协议

        UDP是⽆连接通信协议,即在数据传输时,数据的发送端和接收端不建⽴逻辑连接。简单来说,当⼀台 计算机向另外⼀台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在 收到数据时,也不会向发送端反馈是否收到数据。

        由于使⽤UDP协议消耗资源⼩,通信效率⾼,所以通常都会⽤于⾳频、视频和普通数据的传输例如视频 会议都使⽤UDP协议,因为这种情况即使偶尔丢失⼀两个数据包,也不会对接收结果产⽣太⼤影响。

        但是在使⽤UDP协议传送数据时,由于UDP的⾯向⽆连接性,不能保证数据的完整性,因此在传输重要 数据时不建议使⽤UDP协议。

3.TCP协议

        TCP协议是⾯向连接的通信协议,即在传输数据前先在发送端和接收端建⽴逻辑连接,然后再传输数 据,它提供了两台计算机之间可靠⽆差错的数据传输。在TCP连接中必须要明确客户端与服务器端,由 客户端向服务端发出连接请求,每次连接的创建都需要经过"三次握⼿"。

第⼀次握⼿,客户端向服务器端发出连接请求,等待服务器确认,

第⼆次握⼿,服务器端向客户端回送⼀个响应,通知客户端收到了连接请求,

第三次握⼿,客户端再次向服务器端发送确认信息,确认连接。

4.UDP程序交互流程

> 发送端
 1,创建DatagramSocket对象
 2,创建DatagramPacket对象,并封装数据
 3,发送数据
 4,释放流资源

 > 接收端
 1,创建DatagramSocket对象
 2,创建DatagramPacket对象
 3,接收数据存储到DatagramPacket对象中
 4,获取DatagramPacket对象的内容
 5,释放流资

5.TCP程序交互流程

<1> 客户端
 1,创建客户端的Socket对象
 2,获取Socket的输出流对象
 3,写数据给服务器
 4,获取Socket的输⼊流对象
 5,使⽤输⼊流,读反馈信息
 6,关闭流资源

 <2> 服务器端
 1,创建服务器端ServerSocket对象,指定服务器端端⼝号 2,开启服务器,等待着客户端Socket对象的连接,如有客户端连接,返回客户端的Socket对象
 3,通过客户端的Socket对象,获取客户端的输⼊流,为了实现获取客户端发来的数据
 4,通过客户端的输⼊流,获取流中的数据
 5,通过客户端的Socket对象,获取客户端的输出流,为了实现给客户端反馈信息
 6,通过客户端的输出流,写数据到流中
 7,关闭流资源

三、数据库表常用指令

1、查询所有的数据库表
	show databases; 
2、使用哪个数据库表
	use 数据库名;
3、创建数据库表
	create table <表名>(
		<字段名1> <数据类型> [列级别约束条件][默认值],
		<字段名2> <数据类型> [列级别约束条件][默认值],
		<字段名3> <数据类型> [列级别约束条件][默认值],
		...
	)[engine=引擎][default chaset=字符编码];
注意:
<>中的内容是必须有的,[]可以有也可以没有
最有一个字段后面不加","
[]部分如果没有设置,那么mysql会使用默认的设置

	create table student(
    -> sid int,
    -> sname varchar(15),
    -> age int
    -> );
注意:
1、sql语法不跟java一样严格区分大小写,sql语句大写小写都行,按惯例,所有的sql语句都是大写的,因为小写发送给服务器进行运行的时候,也会先转换成大写再执行
2、严格语法中,数据库名和字段名需要使用反单引号括起来
3、如果数据库名和表名有多个单词组成,惯例使用"下划线命名法"
    
约束:
1、非空(not null)约束
是一个列级别的约束,要求所限定的列不允许放空值进来
create table 表名(
	字段名 数据类型 not null,
    ...
);

 create table teacher(
    -> tid int,
    -> tname varchar(15),
    -> tsex varchar(2),
    -> phone int not null
    -> );

2、唯一性约束,是一个列级别的约束,设定的列不运行插入重复的值
  create table 表名(
	字段名 数据类型 unique,
	...
	);

 create table a(
    -> id int not null,
    -> name varchar(20) unique not null,
    -> pwd varchar(20)
    -> );

3、默认值(default)约束
默认值越是,是一个列级别的约束,所限定的列,当没有插入值的时候,给定一个默认值
create table 表名(
	字段名 数据类型 default 具体的值,
    ...
);
create table tb_02(
    -> id int not null,
    -> uname varchar(20) unique not null,
    -> place varchar(20) default 'wh'
    -> );
into tb_02(id,uname) values(1,'zhangsan');
insert into tb_02(id,uname,place) values(2,'lisi','sh');

4、主键(primary key)约束
主键约束是一个表级别的约束,它等价于 非空 + 唯一约束
它要求所限定的列,非空且唯一
一个表中只能有一个主键

主键约束分为两种:
单主键:通常直接在列的尾部进行声明
create table 表名(
	字段名 数据类型 primary key,
    ...
);

联合主键:主键设计两个列或者两个以上的列,多个列作为主键
	create table 表名(
	    字段名1 数据类型,
    	字段名2 数据类型,
    	字段名3 数据类型,
    	...
         primary key(字段名1,字段名2,字段名3...)
	);

mysql> create table  tb_stu(
    -> stuId int primary key, -- 设置主键
    -> stuName varchar(20) not null
    -> );

mysql> create table tb_cs(
    -> sid int,
    -> cno int,
    -> score double,
    -> primary key(sid,cno) -- 设置联合主键
    -> );

-- 表没有创建主键添加主键
mysql> create table tb_03(
    -> id int,
    -> name varchar(20) not null
    -> );

mysql> alter table tb_03 add primary key(id);-- 添加主键

mysql> alter table tb_03 drop primary key;-- 删除主键


5、外键(foreign key)约束
外键约束,是一种表级别的约束,他用于表示被它修饰的列中的数据,需要参考另一张表的某一个列中的值

create table a表(
	...
    字段名 类型 references b表(某个字段)
    ...
);


create table a表(
	...
	...
    constraint 约束名 foreign key a表中的字段名 references b表(某个字段)
);

四、数据库表的相关操作

-- 如何查看表结构
-- 查看表的字段信息
desc 表名;
describe 表名;

-- 查看建表语句
show create table 表名;

-- 修改表中的原数据
-- 添加主键约束
alter table 表名 add [constraint 主键约束名] primary key(主键字段);

-- 删除外键约束
alter table 表名 drop foreign key 外键约束名;

-- 创建好表之后想要添加外键连接
alter table 表名 add constraint 外键约束名 FOREIGN key(外键字段名) REFERENCES 主表(关联字段名);

-- 删除主键约束
alter table 表名 drop primary key;

-- 创建好表之后想要添加列
alter table 表名 add 字段名 字段数据类型;

-- 修改列类型,长度,以及约束
alter table 表名 modify 列名 数据类型(长度) 约束;

-- 修改列的名称
alter table 表名 change 旧列名 新列名 数据类型(长度)约束;

-- 删除列
alter table 表名 drop 列名;

-- 给表进行重命名
rename table 表名 to 新表名;

-- 修改表的字符编码
alter table 表名 character set 字符编码;

-- 删除表
drop table if exists 表名; -- 表中的数据和表都不在了

-- 删除表中的数据,数据不在了,表还在
truncate table 表名;
delete from 表名;

五、数据库表中的数据操作

①数据库中的增删改操作
show DATABASES;
use test_01;
-- 增删改操作被称为DML语句
-- DML语句用于操作数据库表和视图的数据
-- insert 向表中添加数据
-- update 修改表中的数据
-- delete 删除表中的数据


-- insert into 表名(字段名1,字段名2,字段名3...) values(值1,值2,值3...);
-- 要给几个字段赋值,就写几个字段,默认的就不要写了,要做到一一对应
-- 添加一条信息
insert into tb_dept(deptId,deptName) VALUES(1,'研发部');
-- 添加多条信息
insert into tb_dept(deptId,deptName) VALUES(2,'行政部'),(3,'后勤部'),(4,'保安部');

-- 如果没有指定列名,默认插入所有的信息
insert into tb_emp VALUES(1,'李小龙','男',3200,4);

insert into tb_emp(empName,empSex,empSal) VALUES('狄仁杰','男',20000);


-- update语句
-- update 表名 set 字段名1=值1,字段名2=值2,字段名3=值3,...WHERE 条件表达式;
-- 凡是符合where子句的都会被更新
-- 没有where子句,修改所有的行的数据
-- 部门编号为1的员工的工资加10%
UPDATE tb_emp set empSal=empSal * 1.1 where did = 1;

-- 将所有的员工的工资增加原来的50%
UPDATE tb_emp set empSal=empSal * 1.5;

-- 修改表中狄仁杰的部门号为
UPDATE tb_emp set did = 1 where empName = '狄仁杰';

-- 修改id为1的员工的姓名为吴亦凡
UPDATE tb_emp set empName = '吴亦凡',empSal = 2 where empId = 1;

-- 将2号部门中的男员工的工资加2000
UPDATE tb_emp set empSal = empSal + 2000 where did = 2 and empSex = '男';

-- 如果一个人部门号是4,或者工资小于100,就将工资设为0
UPDATE tb_emp set empSal = 0 where did = 4 or empSal < 100;


-- delete语句
-- delete from 表名 where 条件表达式;
-- 凡是符合条件的行都会被删除,如果没有where子句,则删除表中所有数据
-- 清空表的数据,表还在
-- drop table 表名; -- 删除表
-- truncate table 表名;-- 快速删除表中的数据,表还在

-- 删除两个元素
delete from tb_emp where empName in('吴亦凡','孙悟空');
delete from tb_emp where empName = '曾志伟' or empName = '狄仁杰';
-- 删除所有元素
delete from tb_emp;

select * from tb_emp;
②查询语句
-- 查询语句
-- 使用最频繁的sql语句就是select,其用途就是从一个或者多个表中检索信息
-- select 是DQL语句

-- 查询单列
-- select 列名 from 表名;
-- 从指定的表中查询表出单个指定的列的信息
	select empName from tb_emp;

-- 查询多列
-- select 列名1,列名2,...from 表名;
-- 从指定的表中查询出多个指定的列的数据
	SELECT empName,empSex,empSal from tb_emp;

-- 查询所有的列
-- select * from 表名;
-- * 是一个通配符
-- 在实际工作中,最好不要使用*,因为查询出来不需要的列通常会降低查询的效率
	select * from tb_dept;


-- 使用完全限定的表名
-- 表的完全限定名: 库名.表名;
-- 列的完全限定名: 表名.列名;

-- 对查询到的数据进行排序
-- select 字段名1,字段名2... from 表名 order by 列名;
-- 以升序的形式进行排序
-- 如果不进行排序,则数据获取的时候以它们插入的时候的顺序取出
-- 如果需要排序,就使用order by
	select empName,empSal from tb_emp ORDER BY empSal; 

-- 这是以降序的形式进行排序
	select * from tb_emp ORDER BY empSal DESC;
-- DESC 降序
-- ASC 升序 默认

-- 按多列进行排序
-- select 字段名1,字段名2...FROM 表名 ORDER BY 列名1,列名2...;
-- 以第一个列进行排序,如果出现相等,则会以第二个列进行参考,一次类推
	select * from tb_emp ORDER BY empSal,empId;

-- 过滤数据where
-- select 字段名1,字段名2,...from 表名 where 过滤条件
-- where 子句 可以使用运算符:
-- = 等于
-- !=       <> 不等于
-- < 小于 > 大于 <= 小于等于 >= 大于等于
-- between ... AND...
-- 日期也可以使用这些符号来进行表示,但是有格式要求'yyyy - MM - dd'
-- 日期要使用''单引号括起来,必须给定合法的格式'yyyy -MM - dd'
-- 当某一列没有任何值的时候,称之为NULL
-- 注意:没有值,不是0,空字符串,空白字符串
-- is null 判断是否为空 is not null 非空

-- 高级数据过滤
-- select * from 表名 where 过滤条件1 or 过滤条件2; -- 或者
-- select * from 表名 where 过滤条件1 and 过滤条件2; -- 并且

-- in 运算符可以替换or
-- select * from 表名 where in(值1,值2......); -- 或者
-- in运算符要比or运算符效率高,in 里面可以写另外一条sql语句
-- SELECT * FROM 表名 where not 过滤条件; -- 取反

-- 1、查询单列
	select empName from tb_emp;
-- 2、查询多列
	select empName,empSal from tb_emp;
-- 3、查询所有信息
	select * from tb_emp;
-- as e 给表取一个别名
-- 表名.列名
	select e.empId,e.empName,e.empSal,e.empSex,e.did from tb_emp as e;
-- 4、按照工资进行排序,如果工资相同就按照姓名排序
	select * from tb_emp ORDER BY empSal DESC, empName ASC;

-- 5、查询工资高出10000的员工的姓名和部门编号
	SELECT empName,did from tb_emp where empSal > 10000;

-- 6、查工资在5000 ~ 10000之间的员工的信息
	SELECT * FROM tb_emp where empSal >= 5000 and empSal <= 10000;
	SELECT * FROM tb_emp where empSal BETWEEN 5000 and 10000;

-- 7、查询不是1号部门的员工的信息
	SELECT * from tb_emp where did <> 1;
	SELECT * from tb_emp where did != 1;
	SELECT * from tb_emp where not did = 1;

-- 8、查询没有部门信息的员工
	select * from tb_emp WHERE did is null; 
	select * from tb_emp WHERE did is not null; 

-- 9、模糊查询
-- select * from 表名 where 列名 like 通配符字符串;
-- %匹配出现任意次数的任意字符 %也可以匹配0个字符 %不能匹配null
-- _只能匹配一个字符
-- 查询所有姓李的人的信息
	 select * from tb_emp WHERE empName like '李%';
	 select * from tb_emp WHERE empName like '李_';


use test_01;
-- 有时操作数据库的目的是用于数据的汇总
-- 获取行数
-- 可以获取某列中的最大值,最小值,平均数
-- 标准的sql语句中提供了5个常用的聚合函数
-- avg() 求某列的平均值,avg()函数获取的时候不考虑null值
-- count() 某列的行数
-- 	count(*) 会计算所有的行,包括空行
-- 	count(列名) 只会读取计算指定列中有值的行,不会考虑null行
-- max()某列中的最大值
-- 	max(列名) 不统计null行
-- min()某列中的最小值
-- 	min(列名) 不统计null行
-- sum()将某列的值进行求和
-- 	sum(列名) 不统计null行


-- 分组查询
-- 在没有指定分组查询之前,所有查询的数据都默认在同一个组里面
-- 聚合函数都是对这一组信息进行计算和处理
-- 我们可以使用group by进行分组处理
-- 分别查找某一个部门有多少人
select did,count(*) from tb_emp GROUP BY did;

-- group by 和 select一样,可以通过逗号分隔指定多的列
-- 还可以按照多个列进行分组
select did,count(*) from tb_emp GROUP BY did,empName;

-- 使用分组和聚合函数的时候,select子句,只能存在三种元素
-- 常数
-- 聚合函数
-- group by 子句中的列名    不能使用列的别名


-- having分组条件
-- where 子句,用于指定行所对应的条件
-- having 子句,用于指定组所有的条件
-- having 是分组以后,对分组后的结果进行的再一次过滤
select did,count(*) from tb_emp GROUP BY did having count(*) >= 2;
select * from tb_emp where empSal = (select MAX(empSal) from tb_emp);


-- limit子句
-- 分页
-- 从下标为2的元素开始,往后数3个
select * from tb_emp LIMIT 4,2;
select * from tb_emp;
-- totalSize = 8 总记录条数
-- pageSize 每页显示多少数据
-- totalPage = 总记录条数 / 每页的数据条数
-- 如果有余数就 + 1
-- 如果没有余数,就是当前的总页数
-- LIMIT pageSize * (pageNum -  1),pageSize
上一篇:2021-04-25


下一篇:MySQL