黑马程序员技术交流社区
标题: 【石家庄校区】这又是一篇学习笔记 [打印本页]
作者: 空降的蛙崽 时间: 2018-4-23 16:05
标题: 【石家庄校区】这又是一篇学习笔记
本帖最后由 小石姐姐 于 2018-4-25 17:00 编辑
多线程
进程 : 是一个应用程序在内存中的执行区域,比如一个正在运行的程序,可以有一个或者多个进程
一个正在运行的程序,可以有一个或多个进程,每个进程都会占用一部分的系统资源,如CPU,内存,磁盘,网络等
而线程则是一个进程中的一个执行路径 如:
一个进程中可以有一个或多个线程
每个线程可以执行自己的代码
多个线程各自执行的任务可以同时进行
线程的执行依靠CPU调度分配
单核CPU: 靠CPU不断高速的随机的切换执行的线程, 达到看似同时进行的效果
多核CPU: 每个CPU可能完全执行一个线程, 或者多个CPU各自不断高速随机切换, 更高效
单线程: 同一时间只做一件事情, 安全性高, 效率低.
多线程: 同一时间做多件事, 安全性低, 效率高.
什么是并发? 并发就是并行发生, 同时发生, 多线程就可以实现并发
同步: sync, 同步是指一步接一步的执行, 一个执行完毕再开始执行下一个.
异步: async,同时执行多步, 每个步骤何时结束不确定.
阻塞: 上一行代码正在执行, 还没有执行完毕, 程序就阻塞了, 下一行代码必须等上一行不再阻塞后才能执行
创建线程的第一种方式: 继承Thread类
Thread Thread(): 创建Thead对象
Thread Thread(Runnable r)`: 通过Runnable对象创建Thread对象
Thread Thread(Runnable r, String threadName): 通过Runnable对象创建Thread对象并指定线程名
成员方法
void run()`: 用于让子类重写, 表示该线程要执行的任务. 不能直接调用
void start(): 启动线程, 即让线程开始执行run()`方法中的代码
String getName()`: 获取线程的名称
void setName(String name)`: 设置线程名称
静态方法
static Thread currentThread()`: 返回对当前正在执行的线程对象的引用
static void sleep(long millis)`: 让所在线程睡眠指定的毫秒
多线程实现方式1:
定义类, 继承Thread类, 重写run()方法
步骤:
定义一个类, 继承Thread类
在子类中重写父类的run()方法
创建子类的对象
调用子类对象的start()方法启动线程
main()方法也是执行在一个线程中的,是单线程的, 方法中的代码是一行一行向下执行的
创建线程的第二种方式:实现Runnable接口
实现Runnable接口, 重写run()方法
步骤
多线程中的线程安全问题: 使用同步代码块去解决共享资源问题
同步:多个线程在执行同步的代码时,程序只能按照顺序一个一个去执行
优点:同步安全性高,效率低
同步代码块: 使用synchronized修饰的代码块
作用:
被同步代码块包裹的代码相当于在一个房间内, 锁对象相当于房间的锁
一个线程进入同步代码块, 会把门锁上, 同步代码块外面的线程看到同步代码块内部有线程, 只能在外面等待
直到同步代码块内部的线程执行完毕从代码块中出来, 释放了锁, 外面等待的线程才能随机进去一个
应用位置:
哪些代码属于共享操作, 需要避免安全问题, 就将这些代码放入同步代码块
术语
线程进入同步代码块, 叫获取锁
线程出同步代码块, 叫释放锁
锁是一个任意类型的对象,必须是被所有线程共享的,同步代码块必须配合所对象来使用
出现多线程的安全问题, 检查一下2个方面
对于操作了了共享数据的代码是否是同步的?
同步使用的是否是同一个锁对象?
继承Thread 类和实现Runnable接口在共享资源上有啥区别?
继承Thread类: Thread类中的非静态变量成员变量是每个线程各自拥有的,不能作为共享资源
静态成员变量是所有线程对象共享的,可以作为共享资源
实现Runnable接口: 如果所有的Thread对象都传入同一个Runnable对象,那么
Runnable对象中的非静态成员变量会被所有线程共享,可以作为共享资源
Runnable对象中的静态成员变量也会被所有Thread对象共享,也可以作为共享资源
所以, 继承Thread类方式下,共享资源要定义成Thread类的静态资源
实现Runnable接口方式下,共享资源要定义为Runnable接口的静态或非静态资源,并且所有Thread对象都要传入同一个Runnable对象
线程的生命周期
线程的生命周期中有5种状态
创建: new一个线程对象, 此时还没有调用start()
就绪: 调用start()方法后, 进入就绪状态, 等待CPU执行
运行: 获取了CPU的执行权, 开始运行线程
阻塞: 调用了sleep(), wait(), 或由于IO操作导致阻塞. 阻塞解除后仍会返回就绪状态, 等待CPU执行
销毁: 线程执行完毕
线程之间的通信
wait():使当前此案成处于等待状态,并且会立刻释放锁
notify():随机唤醒一个处于等待状态的线程
notifyAll(): 唤醒全部处于等待状态的线程
注意:这三个方法必须在同步代码块中,且只能用锁对象来调用,否则会抛异常
sleep()和wait()有啥区别?
sleep() : 让当前的线程在指定的时间睡眠, 时间结束后就继续执行.不会释放锁
wait(): 让当前线程等着,知道有人唤醒,会立刻释放锁
线程释放锁的3种情况
死锁??????
死锁: dead lock
同步代码块中的线程不出来, 也不释放锁; 同步代码块外的线程拿不到锁, 只能等在外面.
发生死锁的原因:
同步代码块内的线程, 可能处在死循环, IO阻塞, sleep()状态, 导致内部持有锁的线程无法出同步代码块
多个线程互相持有锁又不释放锁: 两个线程执行的任务都是双层同步代码块, 每层同步都需要一个锁, 两个线程中同步代码块的锁是相反的
死锁的结果: 程序卡死, 无法继续执行
怎么避免死锁:
避免在同步代码块中执行死循环, IO阻塞操作, sleep()
避免多个线程互相持有锁又不释放锁的情况
另一种加锁方式: Lock类
// 创建锁对象, 该锁对象也要所有线程共享唯一一个private Lock lock = new ReentrantLock();
lock.lock(); // 加锁, 相当于执行到synchronized// 同步的代码lock.unlock(); // 释放锁, 相当于同步代码块执行完毕网络
day12网络网络编程概述网络编程:
Socket : 中文译名为 套接字 对协议的一个封装
用于描述IP地址和端口,时一种网络编程机制,通信两端都有Socket
网络通信三要素传输协议: 通信的规则
作用:通信的规则
常见协议:
TCP// 传输控制协议 :
需要建立链接的可靠协议
没有数据传输大小的概念
在传输前需要先建立连接(三次握手)
重发机制, 如果接收方没有接收到信息,发回验证信息,然后发送方会重新发送
所以数据发送时间长,数据流量大
使用场景: 适合准确性要求强的场合,比如金融系统,视频点播(可缓冲)
形成传输数据的通道,通过三次握手完成链接,可靠协议,效率低
UDP// 用户数据报协议:
无连接的不可靠的协议
数据传输大小限制为64K(一个包)
不需要建立连接随便扔
数据发送速度快,发送方只管发送数据,不管你接没接到,所以可能又丢包情况
使用场景:
适合实时性要求强的场合,QQ语音,微信视频,卡掉就是卡掉了,中间空白了
IP 可以使用主机名或域名代替,更容易记忆
端口号:
作用: 标识使用网络通信的进程的逻辑地址,用于定位一个主机上的具体服务
端口号范围: 0 - 65535 前1024个端口时系统保留的端口号
常见服务占用的端口
80: HTTP服务
443: HTTPS服务,安全加密的HTTP
21: FTP服务,文件传输
22: SSH服务,安全加密的远程登陆
23: Telnet服务,远程登陆
举例理解三要素(寄快递)
传输协议:用什么快递
IP地址: XX省XX市XX街道XX号
端口号: X楼
InetAddress概述和测试java.net.包下InetAddress类: 用于表示IP地址对象(包含IP地址和主机名)
static InetAddress getLocalHost() :获取本机的InetAddress对象
getByName():根据主机名或IP的字符串获取主机对象
getLoopbackAddress(): 获取回环地址的InetAddress的对象,
static InetAddress getByAddress(byte[] addr): 根据IP获取InetAddress对象
getHostName(): 获取主机名
getHostAddress(): 获取IP地址
getLocalHost(): 获取本机主机名
ipconfig: 在cmd中输入用于查看本机的IP信息UDP协议发送数据DatagramSocket : 基于UDP协议的Socket
构造方法:
DatagramSocket(): 创建Socket对象并随机分配端口号
DatagramSocket(int port) : 创建Socket对象并指定端口号
成员方法:
send(DatagramPacket p): 发送数据包
receive(DatagramPacket p ): 接收数据,数据保证在DatagramPacket对象中
close(): 关闭通信,释放资源
DatagramPacket 类: UDP数据包
构造方法:
DatagramPacket(byte[] msg, int msgLength, InetAddress host, int port): 创建数据包对象, 指定数据, 目标主机对象, 端口
DatagramPacket(byte[] buf,int length):创建数据包对象,接收数据为length的数据,存入byte数组中
成员方法
InetAddress getAddress(): 获取数据包发送方的InetAddress对象
byte[] getData(): 获取包中的数据, 以byte数组形式
int getLength(): 获取数据的长度, 即byte数组的长度
int getPort(): 获取发送方端口号
UDP协议接收数据端口号错误,数据可以正常发出,不会出现异常,但是收不到数据
BindException : 端口绑定异常 端口号不能重复,
TCP协议发送数据构造方法: Socket(InetAddress add, int port): 创建TCP客户端对象
成员方法:
OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
InputStream getInputStream(): 获取输入流, 用于接收数据
void close(): 释放资源
TCP发送数据步骤
- // 1. 创建客户端Socket对象(建立连接)Socket socket = new Socket(InetAddress地址, 端口号);// 2. 获取输出流对象OutputStream outputStream = socket.getOutputStream();// 3. 发送数据outputStream.write(byte数组);// 4. 释放资源socket.close();TCP协议接收数据
java.net.ServerSocket`: TCP服务端
构造方法
成员方法
Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
void close(): 关闭Socket
反射Reflect反射:Reflect
在运行时,我们可以获取任意一个类的所有方法和属性(包括私有的)
在运行时,让我们调用任意一个对象的所有方法和属性(包括私有的)
反射的前提:要获取类的对象(Class对象)
获取字节码对象的三种方式 //建立了一个student类
通过Object的getClass()方法获取,必须有对象
student s = new student();
Class clazz = s.getClass;
通过类名获取字节码对象
Class clazz = Student.class;
static Class<?> forName(String className)
Class clazz = Class.forName(" 全部的类名")
反射获取构造方法并创建对象反射使用的相关类和方法java.lang.Class类: 类的字节码对象
获取构造方法:
Constructor<?>[ ] getConstructors(): 以数组形式返回该类中的所有public的构造方法,如果没有public的,则数组长度长度为0
Constructor<?>[ ] getDeclaredConstructors(): 以数组形式返回该类中所有权限的构造方法,包括私有的,如果该类时接口,基本类型,数组,void,则数组长度为0
Constructor<?>[ ] getConstructors(Class<?>... parameterTypes): 根据参数列表返回指定的public的构造方法,参数列表填写参数的字节码对象
Constructor<?>[ ] getDeclaredConstructors(Class<?>... parameterTypes):根据参数列表返回指定的所有权限的构造方法,包括私有的,参数列表填写参数的字节码对象
创建对象:
T newInstance()
反射获取public成员变量:设置和获取值成员变量方法:getFields(): 获取公共的成员变量
getFields(): 获取所有public的成员变量
getDeclaredFields(): 获取所有权限的成员变量.包括私有的
getFields(String fieldName): 通过指定的成员变量名获取指定的punlic成员变量
getDeclaredFields(String fieldName): 通过指定的成员变量名获取指定的所有权限的成员变量.包括私有的
成员变量对象:Object get(Object obj): 获取指定对象的属性值,传入对象,返回该对象的属性
反射获取成员方法并调用获取成员方法:
Method [ ] getMethods(): 返回所有public的方法数组
Method [ ] getDeclaredMethods(): 返回所有权限的方法数组
Method getMethods(String name,Class<?>... parameterTypes): 获取public的方法,传入方法名和方法形参字节码对象
HTML :超文本标记语言扩展名为.html 或者.htm
空格:&npsp
<hr/ > 横线
<pre>:原生标签,把copy过来的内容原封不动的粘过来
字体标签<font>文字</font>
<font>标签的属性:
color:字体的颜色
size:字体的大小
face: 字体
标题标签<h1>...<h6>
段落标签<p>
粗体标签<b>
斜体标签<i>
下划线标签<u>
居中显示<center>
图片标签<img>属性:
src: 图片的来源路径
width: 图片的宽度
height: 图片的高度
alt:图片找不到显示的内容
图片引入的路径问题?
路径:相对路径
同一路径可以直接写文件名或 ./ 文件名
上一级目录: ../
列表标签有序列表<ol>
<li></li>
</ol>
type属性 :
1 数字类型
a 英文类型
i 罗马字符
start : 从哪里开始,
无序列表<ul>
<li></li>
</ul>
type属性:
disc :实心点
circle:空心圆
square:方块
超链接标签<a>
属性:
href: 链接的路径
target: 打开的方式
_self : 在自身页面打开
_blank : 新打开一个窗口
_parent :
表格标签<table>
<tr> :行
<td> :列
属性:
width: 表格宽度
height:表格高度
border: 边框
aligh: 表格水平位置:
left :居左
right: 居右
center:居中
<td>的属性:
合并表格:
colspan = "列数"
rowspan = "行数"
HTML的表单标签<from>常用属性:action属性: 提交的路径,如果没指定默认提交到当前页面
method属性: 请求的方式,GET和POST,默认是GET
常问的面试题:GET和POST属性的区别?
GET: 数据会显示到地址看重 , 提交是有大小限制的,请求行里边
POST: 数据不会显示到地址栏中 . 相对来说安全一点,提交没有大小限制,请求体中
<input type = "text"> :文本框 name : 表单名称,要有名字方便后台接收
value : 文本框的默认值
size : 设置文本框的长度
maxlength : 设定几个数字 就只能接收几个数字
readonly : 不允许输入的.只读的
<input type = "password"> :密码框 name : 表单名称,要有名字方便后台接收
value : 文本框的默认值
size : 设置文本框的长度
maxlength : 设定几个数字 就只能接收几个数字
<input type = "radio"> :单选按钮 name : 表单名称,要有名字方便后台接收
value :单选按钮的默认值
checked : 单选按钮默认被选中
<input type ="checkbox"> :复选框 name : 表单名称,要有名字方便后台接收
value :单选按钮的默认值
checked : 单选按钮默认被选中
<input type ="button"> :普通按钮<input type ="submit"> :提交按钮<input type ="reset"> :重置按钮<input type ="file"> :文件上传(可浏览上传)<input type ="hidden"> :隐藏字段<input type ="image"> :图片按钮<select> : 下拉列表<textarea> : 文本域HTML5扩展的表单标签(不是所有浏览器都支持)<input type = "email"> :只能输入邮箱形式的
<input type = "date"> :只能输入日期形式的
<input type = "number"> :只能输入数字
<input type = "color"> :颜色板 可以直接选
此致......
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |