Java入门第二阶段——多线程+网络编程

多线程基本概念--程序--进程--线程
程序:Program,是一个指令集合
进程:Process,(正在执行中的程序)是一个静态的概念
进程是程序的一次静态执行过程,占用特定的地址空间,每个进程都是独立的,由三部分组成cpu,data,code
缺点:内存的浪费,cpu的负担
线程:是进程中一个“单一的连续控制流程”,又被称为轻量级进程
一个进程可以拥有多个并行的线程
一个进程中的线程共享相同的内存单元/内存地址空间?可以访问相同的变量和对象,而且它们从同一堆中
分配对象?通信、数据交换、同步操作,由于线程间的通信是在同一地址空间上进行的,所以不需要额外
的通信机制,这就使得通信更简便而且信息传递的速度也更快

进程:作为资源分配的单位,每个进程都有独立的代码和数据空间(进程上下文)进程间的切换会有较大的开销
(不同内存地址上的切换),在操作系统中能同时运行多个程序,系统在运行时,会为每个进程分配不同的
内存空间

线程:调度和执行的单位,线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程
有独立的运行栈和程序计数器,线程切换的开销小(同一内存地址上的切换),在同一应用程序中,有多
个顺序流同时执行,除了CPU之外,不会为线程分配内存空间(线程所使用的资源是它所属的进程的资源)
线程组只能共享资源

一个进程中包含了N多个线程,如果线程结束,进程并不一定结束
进程结束,线程都将结束
CPU调度执行的是线程

通过继承Thread类实现多线程
实现多线程的步骤
1)继承Thread类
2)重写run()方法
3)通过start()方法启动线程
一定的缺点:Java中的类是单继承的,一旦继承了Thread类,就不允许继承其他的类
通过是实现接口Runnable实现多线程
1)编写类实现Runnable接口
2)实现run()方法
3)通过Thread类的start()方法启动线程
静态代理模式
Thread -->代理角色
MyRunnable-->真实角色
代理角色和真实角色实现共同的接口Runnable

举例:
你结婚------真实角色
婚庆公司------代理角色
共同拥有结婚的接口--------结婚的方法

线程状态--线程的生命周期
新生状态(new 创建线程类的对象)
调用start()方法后成为就绪状态
就绪状态(万事俱备,只欠"CPU",有资格,无资源)
执行run()方法后,成为运行状态
运行状态(有资格,有资源)------------>阻塞状态(无资格,让资源)------>就绪状态(等待下一次的CPU调配)
终止状态/死亡状态
(1)执行完了run()方法中的代码
(2)调用stop()方法 (已过时)
(3)抛出了未捕获的异常

总结:1.不知道什么时候会被选中执行.2.遇到等待IO输入或其他耗时操作,由运行状态进入阻塞状态
3.导致阻塞的事件结果,就绪状态,等待CPU选中执行4.运行状态时,给定的时间片内没有执行完run方法
中的代码,进入到就绪状态,下一次被CPU选中时,从上次断掉的地方继续执行

获取线程基本信息的方法
1)static Thread currentThread()    返回目前正在执行的线程
2)final String getName()  返回线程的名称
3)final boolean isAlive()    判断线程是否处于活动状态

多线程的安全性问题
抢线程导致数据错乱

暂停线程执行sleep---yield--join--stop
final void join()调用该方法的线程强制执行,其他线程处于阻塞状态,该线程执行完毕后,其他线程再执行
static void sleep(long millis)使用当前正在执行的线程休眠millis秒,线程处于阻塞状态
static void yield() 当前正在执行的线程暂停一次,允许其他线程执行,不阻塞,线程进入就绪状态,如果
没有其他等待执行的线程,这个时候当前线程就会马上恢复执行
final void stop()   强迫线程停止执行,已经过时,不建议使用

总结:
sleep不会释放锁,Sleep时,别的线程也不可以访问锁定对象
yield让出CPU的使用权,从运行态直接进入就绪态,让CPU重新挑选哪一个线程进入运行状态
join当某个线程等待另一个线程执行结束后,才继续执行时,使调用该方法的线程在此之前执行完毕,
也就是等待调用该方法的线程执行完毕后再往下继续执行

线程的优先级问题
final int getPriority()     获取线程优先级
final void setPriority(int priority)  设置线程优先级

线程同步--具体实现
同步实现的方式
synchronized(obj){//中的obj称为同步监视器}
同步方法
同步方法的同步监视器为当前对象this
public synchronized...方法名(){}
同步监视器只能是对象,推荐使用共享资源的对象,可以当前对象this,也可以是其他的对象

死锁--死锁的解决办法
死锁产生的原因:多线程操作时,互相等待对方的资源
解决办法:不要让两个对象同时持有对象锁,采用互斥方式来解决

死锁的避免
银行家算法:该算法需要检查申请者对资源的最大需求量,如果系统现存在各类资源可以满足申请者的
请求,就满足申请者的请求。这样申请者就可很快完成其计算,然后释放它占用的资源,从而保证了系统
中所有进程都能完成,所以可避免死锁的发生。(计算资源大小,计算出来后,永远按照从大到小的方式
获得锁)

生产者消费模式的实现
产生的问题:数据错乱,重复生产、重复取走
数据错乱:synchronized同步方法解决
重复生产-重复取走:线程间的通信解决
线程间通信的方法(只能在同步方法或者同步代码块中使用
wait():调用 wait()方法的线程进入等待池,进行等待,等待池中的线程不去竞争对象锁,直到其他的线程
通知,才会进入锁池
notify():随机唤醒一个在该对象上等待的线程,被唤醒的线程进行锁池,开始竞争该对锁上的锁
notifyAll():唤醒所有在该对象上等待的线程,优先级高的线程有可能先竞争到对象锁

网络编程
网络:一组相互连接的计算机,多台计算机组成,使用物理线路进行连接
双绞线----->局域网                        光纤----->城域网                  海底光缆或者是卫星----->广域网
网络连接的功能      交换数据     共享资源
网络编程三要素
1)IP地址:唯一标识网络上的每一台计算机,两台计算机之间通信的必备要素
2)端口号:计算机中应用的标号(代表一个应用程序),0-1024系统使用或保留端口,端号口占2个字节
所以有效端口0-65535
3)通信协议:通信的规则 TCP、UDP

IP---端口---Socket含义
IP地址用于标识网络上的唯一一台计算机,共32位,4个8位二进制数组成
IP地址分为:IPv4和IPv6
IPv4:点分十进制表示法(用点分开)
IPv6:十六进制表示法
IP地址=网络ID+主机ID
网络ID:标识计算机或网络设备所有的网段
主机ID:标识特定的主机或网络设备
A类:8位网络+24位主机    前8位取值范围:1-126
B类:16位网络+16位主机   前8位取值范围:128-191
C类:24位网络+8位主机    前8位取值范围:192-223
D类:用于组播通信            前8位取值范围:224-239
E类:用于科研                   前8位取值范围:240-255   
特殊IP地址:
1)127.0.0.1本机回环地址,用于本机测试
2)255.255.255.255当前子网,一般用于当前子网广播信息
端口号:虚拟的概念,使用0-65535之间的整数,用于标识不同的应用程序
每个网络程序都会至少有一个端口号
Socket含义:相当于写信时候的邮筒
Socket称为"套接字",是计算机之间通信的一种约定或一种方式,通过Socket这种约定,一台计算机可以
接收其他计算机的数据,也可以向其他计算机发送数据
每一个客户端都使用一个Socket对象表示,服务器端使用ServerSocket等待客户端的连接
ServerSocket有个accept()方法,时刻监听是否有客户端发出请求

TCP和UDP协议的区别
数据的传输
网络参考模式
1)OSI参考模型:开放系统互连参考模型(Open System Interconnect)
应用层:对数据进行封装
表示层:对数据加标识
会话层:加标识
传输层:对数据打包完毕
网络层:给数据加IP地址
数据链路层:通过什么样的方式去
物理层:通过物理设备0-1代码传输
2)TCP/IP参考模型:传输控制/网际协议 Transfer Controln Protocol/Internet Protocol
应用层:应用层、表示层、会话层-----http协议、ftp
传输层:传输层------常见协议UDP,TCP----程序员所处层
网际层:网际层-----IP
网络接口:数据链路、物理层
TCP:一种面向连接(连接导向)的、可靠的、基于字节流的运输层(Transport layer)通信协议
特点:1.面向连接...2.点到点的通信..3.高可靠性:三次握手..4.占用系统资源多、效率低
生活案例:打电话
TCP通信双方需要建立连接,建立连接时,双方存在主次之分 C-S模式,S需要时刻备战,一直监听
UDP通信双方不需要建立连接,通信双方完全平等
UDP:一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务
特点:
1)非面向连接,传输不可靠,可能丢失
2)发送不管对方是否准备好,接收方收到也不确认
3)数据报的大小限制在64k以内
生活案例:发短信

TCP协议数据传递细节
TCP通信原理(基于IO流的编程)
服务器创建ServerSocket,在指定端监听并处理请求
客户端创建Socket,向服务器发送请求

UDP协议数据传递细节
1)不需要利用IO流实现数据的传输
2)每个数据发送单元被统一封装成数据包的方式,发送方将数据包发送到网络中,数据包在网络中
去寻找他的目的地
3)DatagramSocket:用于发送或接收数据包
4)DatagramPacket:数据包
发送方:1)发送的数据是什么  2)发送数据的大小  3)发到哪里去IP地址  4)对方的监听端口
接收方:1)byte[]数组   2)接数据的长度(数组的长度)  3)getData()拆包  getLength()获取真实数据长度

InetAddress类(无构造方法)
封装计算机的IP地址,不包含端口号
1)String getHostAddress()获得IP地址
2)String getHostName()获得主机名
3)static InetAddress getByName(String host)根据主机名获取IP地址
InetSocketAddress类(有构造方法)
IP地址+端口号,用于socket通信

URL类(Uniform Resource Locator)
统一资源定位符,由4部分组成:协议、存放资源的主机域名、端口号和资源文件名
https://www.baidu.com:80/index.html#aa?username=bjsxt&pwd=bjsxt

多线程和并发编程
实现线程前两种方法的缺点
1)没有返回值
2)不支持泛型
3)异常必须处理
实现线程的第三种方式
实现Callable接口,重写call方法
Callable功能更强大
1)Future接口位于java.util.concurrent包中,可以对具体Runnable、Callable任务的执行结果进行取消
(cancel方法,尝试取消执行此任务),查询是否完成(isDone方法)、获取结果(get方法,等待完成
然后检索其结果)等
2)FutureTask是Future接口的唯一的实现类
3)FutureTask同时实现了Runnable,Future接口。它既可以作为Runnable被线程执行,又可以作为
Future得到Callable的返回值

线程同步Lock锁
Lock锁:对需要上锁的地方上锁
1)JDK1.5后新增的功能
2)与Synchronized相比,Lock可提供多种锁方案,更灵活
3)Java.util.concurrent.lock中的Lock是一个接口,它的实现类是一个Java类,而不是作为语言的特性
(关键词)来实现
注意:如果同步代码有异常,要将unLock()放到finally中
步骤
1)创建Lock对象
2)调用lock()方法上锁
3)调用unlock()方法解锁

Lock与synchronized区别
1)Lock是显示锁(手动开启和关闭锁,别忘关闭锁)synchronized是隐式锁
2)Lock只有代码块锁。synchronized有代码块锁和方法锁
3)使用Lock锁,JVM将花费较少的时间来调度线程,性能更好,并且具有更好的扩展性(提供能多的子类)
4)Lock确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定
的代码,则它将一直等待(即被阻止),知道该对象被释放。lock()方法会对Lock实例对象进行加锁,
因此所有对该对象调用lock()方法的线程都会被阻塞,直到该Lock对象的unlock()方法被调用

线程池
创建和销毁对象是非常耗费时间的
生活案例:共享单车
技术案例:线程池、数据库连接池
JDK1.5起,提供了内置线程池
线程池的好处
1)提高响应速度(减少了创建新线程的时间)
2)降低资源消耗(重复利用线程池中线程,不需要每次都创建)
3)提高线程的可管理性:避免线程无限制创建、从而销毁系统资源,降低系统稳定性,甚至内存溢出
或者CPU耗尽
线程池的应用场合
1)需要大量线程,并且完成任务的时间短
2)对性能要求苛刻
3)接受突发性的大量请求
使用线程池执行大量的Runnable命令
使用线程池执行大量的Callable任务

任务调度Task_Timer
任务:就是事情
调度:在不同时间点或者在指定的时间点或者间隔多长时间我去运行这个任务
就是生活中的闹钟
相关的类:Timer类:位于java.util包中

ThreadLocal-----JDK底层
ThreadLocal:直译为“本地线程”,其实它就是一个容器,用于存放线程的局部变量
作用:为解决多线程程序的并发问题
案例:
实现一个序列号的生成器程序

ThreadLocal的使用场景
用来解决数据库连接、Session管理等
ThreadLocal在数据库连接上的应用
当你在一个类中使用static成员变量时,一定要问自己这个static成员变量需要考虑“线程安全吗?”
(也就是说多个线程需要自己独立的static成员变量吗?)如果需要那就需要使用ThreadLocal

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值