IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 知识梳理(五) -> 正文阅读

[网络协议]知识梳理(五)

目录

一、多线程

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
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-26 12:23:00  更:2021-07-26 12:23:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/17 3:26:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码