4/10学习笔记

Thread vs Runnable

创建线程的两种方式:
1继承Thread类:
4/10学习笔记_第1张图片
run方法里面写线程的逻辑代码。
2.实现runable接口
4/10学习笔记_第2张图片
方法比较:
1.由于java类只能继承一个父类,但是可以实现多个接口,runnable接口方法创建线程可以避免这种缺陷。
2.通过继承Thread类的方法创建的线程,不能操作同一份资源。
(火车站买票,一共5张票,继承Thread类的线程各自卖出了5张票,没有做到操作统一资源。)
4/10学习笔记_第3张图片
线程的生命周期
4/10学习笔记_第4张图片
创建:Thread td = new Thread();
就绪:td.start();(等待CPU资源,具备运行条件,不一定在运行中)
运行:获取了CPU资源,执行run方法。
终止:run方法执行完毕,或者td.stop();(后者被淘汰)
阻塞:执行中的线程因为某些原因停止执行,回到就绪状态,或者td.sleep()让线程休眠;

锁:当资源可以同时被多个线程操作时,就极有可能出现资源不同步的错误,为了防止这种错误,把资源用锁锁起来,这样就保证了操作资源的线程至多一个。关键字synchronized用于加锁。线程执行到用synchronized标注的方法时,就会检查对象锁是否释放,没有释放就会等待,释放后线程取得对象锁就可以执行synchronized方法。执行完毕后释放对象锁。
死锁:线程要执行synchronized需要对象锁,如果对象锁释放的条件是线程获得对象锁,这样互相等待的现象叫死锁。

thread、notify、join、yield的方法说明
thread:
currentThread():返回当前线程对象
isAlive判断线程是否执行
setPriority()设置优先级
getPriority()得到优先级
setName()设置线程名字
getName()得到线程名字
notify:唤醒等待对象锁的线程。
join:调用该方法的线程优先执行,执行完毕后,继续执行当前线程。当前线程为阻塞状态。
yield:线程暂停,执行其他线程。调用该方法的线程为就绪状态,线程暂停后,会选择优先级相同或更高的线程执行。
线程异常处理:
方法1:try…catch…
方法2:设置异常处理器
异常处理器分为:线程异常处理器、全局异常处理器。
线程异常处理器:
4/10学习笔记_第5张图片
全局异常处理器:
4/10学习笔记_第6张图片
方法3:利用Future
创建一个线程池,调用submit(可能出现异常的线程对象),返回Future,在调用Future的get方法获得结果。
4/10学习笔记_第7张图片
4/10学习笔记_第8张图片
守护线程
守护线程:为其他线程服务的线程。
设置线程为守护线程:Thread.setDaemon(true);(必须在start()前调用,否则会报illegalThreadStateException异常。)
守护线程产生的子线程也是守护线程
守护线程不能完成类似读写等操作,因为守护线程依赖于用户线程,一旦用户线程结束,守护线程也随之结束了,程序就崩溃了。

Java Socket

网络基础知识
tcp/ip协议:
4/10学习笔记_第9张图片
4/10学习笔记_第10张图片
ip地址:是每个计算机的唯一标识。
端口号:是每个程序的唯一标识。(qq只能给qq发消息,而不能给微信发消息)。

InetAddress类:
在这里插入图片描述
InetAddress类常用方法:
4/10学习笔记_第11张图片
URL:
4/10学习笔记_第12张图片
URL方法:
4/10学习笔记_第13张图片
URL读取页面内容:

4/10学习笔记_第14张图片
Socket:
4/10学习笔记_第15张图片
基于TCP的Socket通信:
服务器端:
4/10学习笔记_第16张图片
客户端:
4/10学习笔记_第17张图片
服务端代码:
4/10学习笔记_第18张图片
4/10学习笔记_第19张图片
客户端代码:
4/10学习笔记_第20张图片
服务端对应多客户端:
1.建线程类,用于做服务端和客户端之间的通信。
2.服务端循环监听,启动线程
4/10学习笔记_第21张图片
基于UDP的Socket通信:
服务端:
4/10学习笔记_第22张图片
代码实现:
4/10学习笔记_第23张图片
客户端:
4/10学习笔记_第24张图片
代码实现:
4/10学习笔记_第25张图片
服务端回应客户端:
4/10学习笔记_第26张图片
客户端接受服务端的回应:
4/10学习笔记_第27张图片

synchronized解析

作用:在这里插入图片描述
用法:
4/10学习笔记_第28张图片
同步代码块锁:
基本用法:
在这里插入图片描述
结果:两个线程轮流执行
两个以上同步代码块用两把不同的锁:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结果:线程1执行第2个同步代码块的同时,线程2执行第1个同步代码块。
原因:线程1执行完第1个同步代码块时释放锁,转而执行第2个同步代码块,同时线程2获得锁后执行第1个同步代码块。

两个以上同步代码块用相同的锁:
在这里插入图片描述
在这里插入图片描述
结果:线程1分别执行两个同步代码块,全部结束后,线程2在执行。
原因:线程1执行完第1个同步代码块时,因为第2个同步代码块使用的锁和第1个相同,所以无需释放锁,因此线程2没有机会执行,直到线程1结束。

类锁的用法:
4/10学习笔记_第29张图片
形式1:
在这里插入图片描述
加static:分别执行
不加static :同时执行

形式2:
4/10学习笔记_第30张图片
参数为this,同时执行
参数为图示,分别执行

线程1访问同步方法,线程2访问非同步方法:
结果并不会轮流执行,原因是synchronized只作用于方法体内;没加synchronized不受影响;

存在两个线程,两个同步方法:
线程1执行同步方法1,结束,线程2执行同步方法2,结束。

存在两个线程,1个非静态同步方法,1个静态同步方法:
同时执行

在同步方法中抛出异常:
抛出异常后会自动释放锁,以便其他线程执行同步方法。

总结:
一把锁只能被一个线程获得,没有获得锁的线程必须等待。
实例都有对应的一把锁,不同实例互不影响。
锁对象是
.class和静态同步方法时,所有对象都用同一把类锁。
方法执行完毕或者抛出异常后都会自动释放锁
*

synchronized的缺陷:
4/10学习笔记_第31张图片

Java多线程之内存可见性

原子性:完整地执行一段代码,期间不可以中断或完全不执行。
概念:
4/10学习笔记_第32张图片
4/10学习笔记_第33张图片
4/10学习笔记_第34张图片
4/10学习笔记_第35张图片

synchronized实现可见性:
4/10学习笔记_第36张图片
4/10学习笔记_第37张图片
4/10学习笔记_第38张图片
volatile实现内存可见性:
4/10学习笔记_第39张图片
4/10学习笔记_第40张图片

保证操作原子性:

4/10学习笔记_第41张图片
使用场合:
4/10学习笔记_第42张图片
synchronized和volatile的比较:
4/10学习笔记_第43张图片

你可能感兴趣的:(4/10学习笔记)