1.线程的同步机制(重点)
1.1 基本概念
当多个线程同时访问同一种共享资源时可能会造成数据的覆盖和不一致等问题,此时就需要对线程之间进行协调和通信,该方式就叫线程的同步机制。
如:
2003年左右 银行卡业务 存折 对应同一个账户
1.2 解决方案
由程序结果可知:当两个线程同时进行取款操作时,会导致最终的账户余额不正确。
引发原因:线程一还没有完成取款操作时,线程二就已经开始执行。
解决方案:等线程一执行完毕取款后再执行线程二,将线程的并发操作修改为串行操作即可
带来问题:多线程串行执行会造成执行的效率比较低,因此建议能不用则尽量不要用, 并且锁定的代码范围应该越小越好。
1.3 实现方式
在Java语言中使用synchronized关键字来实现线程的同步,叫做同步锁/对象锁,具体实现方式如下:
(1)使用同步语句块的方式实现
synchronized(对象的引用){
编写所有需要锁定的代码块;
}
(2)使用同步方法的方式实现,也就是让synchronized关键字修饰整个方法;
该方式等价于synchronized(this){}的方式,推荐使用该方式
1.4 实现原理
多个线程启动后同时抢占共享资源,当其中一个线程抢到共享资源后则进行加锁处理,此时其它线程只能进入阻塞状态,直到该线程执行完毕所有锁定代码后则自动释放对象锁,此时阻塞状态的线程再次抢占共享资源,抢到的线程加锁去执行,抢不到的线程继续保持阻塞。
1.5 死锁(了解)
线程一执行的代码:
public void run(){
synchronized(a){ => 线程一已经持有对象锁a,等待对象锁b
synchronized(b){
...;
}
}
}
线程二执行的代码:
public void run(){
synchronized(b){ => 线程二已经持有对象锁b,等待对象锁a
synchronized(a){
...;
}
}
}
建议:
在以后的开发中尽量不要使用同步语句块的嵌套结构。
1.6 Object类中的常用方法
void wait() - 用于让当前线程进入等待状态,直到其它线程调用notify()
或notifyAll()方法之前。
void wait(long timeout) - 用于让当前线程进入等待状态,等待参数指定的毫秒数。
void notify() - 用于唤醒等待的单个线程。
void notifyAll() - 用于唤醒等待的所有线程。
2.网络编程的常识
目前主流的网络通讯软件有:微信、QQ、陌陌、YY、飞信、阿里旺旺、...
在吗?
2.1 七层网络模型(熟悉)
ISO(国际标准委员会组织)将数据的传递从逻辑上划分为以下七层:
应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
当发送数据时,需要按照上述七层从左向右依次进行加包处理,然后再发送出去;
当接收数据时,需要按照上述七层从右向左依次进行拆包处理,然后再显示出来;
2.2 常见的协议(熟悉)
协议 - 本质上就是一种约定,用于规定通信双方需要遵循的规则。
http协议 - 超文本传输协议,主要用于浏览网页。
ftp协议 - 文件传输协议,主要用于上传和下载文件。
tcp协议 - 传输控制协议,主要用于进行数据的传输和通信。
udp协议 - 用户数据报协议,主要用于进行数据的传输和通信。
ip协议 - 互联网协议,是上述协议的底层协议。
... ...
2.3 IP地址(重点)
如:
192.168.1.1 - 是绝大多数路由器的登录地址,可以进行Mac地址的绑定/过滤。
IP地址是互联网中的唯一地址标识,本质上是由32位二进制组成的整数,叫做ipv4,当然也有128位二进制组成的整数,叫做ipv6,目前的主流还是ipv4。
日常生活中采用点分十进制表示法进行IP地址的描述,也就是将每个字节的二进制转换为一个十进制整数,不同的十进制整数之间采用小数点分隔。
如:
0x01020304(十六进制) => 1.2.3.4
查看IP地址的方式:
Windows系统的dos窗口中使用命令 ipconfig 或者 ipconfig/all 查看
Linux系统的终端窗口中使用命令 ifconfig 或者 /sbin/ifconfig 查看
2.4 端口号(重点)
IP地址 - 可以定位到具体某一台设备中。
端口号 - 可以定位到具体某一个进程中。
网络编程需要提供: IP地址 + 端口号。
端口号本质上是由16位二进制组成的整数,表示的范围是:0 ~ 65535,其中0 ~ 1024之间的端口号通常被系统占用,因此编程从1025开始使用。
3.基于tcp协议的编程模型(重中之重)
3.1 编程模型
服务器:
(1)创建ServerSocket类型的对象,并提供端口号(大插排);
(2)等待客户端的连接请求,调用accept()方法;
(3)使用输入输出流进行通信;
(4)关闭Socket并释放有关的资源;
客户端:
(1)创建Socket类型的对象,并提供服务器的IP地址和端口号(充电器);
(2)使用输入输出流进行通信;
(3)关闭Socket并释放有关的资源;