多线程-死锁 【了解】
多线程-生产者消费者案例 【重点】
多线程-线程状态 【重点】
多线程-线程池 【重点】
网络编程-相关概念 【了解】
网络编程-UDP编程 【重点】
死锁
什么是死锁
多个线程互相获取了对方的锁,从而导致程序无法继续往下执行,卡死的一种现象
结论:以后不要编写锁嵌套的代码,非常容易出现死锁
多线程-生产者消费者案例
线程通信
什么是线程通信
多个线程之间的一种交流、沟通和协作机制,有了这种机制之后,可以让多线程的执行按照一定的规律进行
我们知道Java中的多线程是抢夺式执行,随机的在多个线程之前交替执行,无法精确控制线程的执行,
以及每个线程的执行次数,但是使用线程通信技术就可以做到控制线程按照一定的规律的执行。
实现线程通信这种协作机制,需要依赖等待唤醒机制,线程通信的经典案例是生产者消费者案例
所以以后我们听到这三个词(线程通信、等待唤醒机制和生产者消费者案例)其实说的都是一个内容
什么是等待唤醒机制
使用等待和唤醒的方法来实现的一种机制
这些方法都是定义在Object类中的方法
void wait():无限等待,必须唤醒才会醒来
void wait(long timeout)
void wait(long timeout, int nanos)
void notify():随机唤醒单个正在等待的线程
void notifyAll():唤醒所有正在等待的线程
等待唤醒的方法必须使用在同步代码中,必须使用锁对象进行调用
案例一:控制线程按照顺序输出hello和world
hello
world
hello
world
...
思路:等待唤醒机制+标记
定义标记:boolean
true:轮到hello执行
false:轮到world执行
hello
判断标记
true
执行hello线程
修改标记为false
唤醒等待的线程
false
hello线程等待
world
判断标记
false
执行world线程
修改标记
唤醒等待的线程
true
world线程等待
案例二:生产者消费者案例
生产者
判断标记
true
生产者生产汉堡
修改标记为false
唤醒等待的线程
false
生产者等待
消费者
判断标记
false
消费者吃汉堡
修改标记为true
唤醒等待的线程
true
消费者等待
面试题一:wait()和sleep()的区别
1、所属类和定义不同
wait():Object类中的方法,有三个重载,其中包含一个空参的,非静态的
sleep():Thread类中的方法,有两个重载,必须传递参数,没有空参,静态的
2、使用限制不同
wait():只能使用在同步中,并且必须使用锁对象进行调用
sleep():可以使用在同步中,也可以不使用在同步中,类名.进行调用
3、是否释放锁的不同
wait():释放锁
sleep():如果使用在同步中,不会释放锁
面试题二:Object类中的方法有哪些?
面试题三:Vector和ArrayList的异同
Hashtable和HashMap的异同
StringBuffer和StringBuilder的异同
Vector和ArrayList的异同
相同点:
都是List体系下的实现类
底层都是数组结构
不同点:
1、
ArrayList是线程不安全的,不同步的(没有加锁),但是执行效率高
Vector是线程安全 ,同步的(加了锁),但是执行效率低
2、
ArrayList出现晚一点(JDK1.2),集合的体系结构(集合框架)也是JDK1.2出现的,方法命名简短
Vector出现早一点(JDK1.0),方法命名太长
总结:ArrayList是用于替代Vector的,开发中永远不选Vector,只有面试题或者老的代码中才可能见到它
使用建议:
Vector永远不选
单线程:ArrayList
多线程:
CopyOnWriteArrayList类
List list = Collections.synchronizedList(new ArrayList(...));
Hashtable和HashMap的异同
相同点:
都是Map体系下的实现类
底层都是哈希表结构
不同点:
1、
HashMap是线程不安全的,不同步的(没有加锁),但是执行效率高
Hashtable是线程安全 ,同步的(加了锁),但是执行效率低
2、
HashMap允许存储null键和null值
Hashtable不允许存储null键和null值
总结:HashMap是用于替代Hashtable的,开发中永远不选Hashtable,只有面试题或者老的代码中才可能见到它
使用建议:
Hashtable永远不选
单线程:HashMap
多线程:
ConcurrentHashMap类
Map<K,V> list = Collections.synchronizedMap(Map<K,V> m)
StringBuffer和StringBuilder的异同
相同点:
都是表示可变字符串
内部的方法和使用方式基本都相同(有兼容的API)
不同点:
StringBuilder是线程不安全的,不同步的(没有加锁),但是执行效率高
StringBuffer是线程安全 ,同步的(加了锁),但是执行效率低
使用建议:
单线程:StringBuilder
多线程:StringBuffer
Enumeration和Iterator的异同
相同点:
Enumeration:枚举
Iterator:迭代器
都是用于对集合进行遍历的工具
只不过Enumeration是老的遍历工具,针对的是Vector集合等进行遍历的
不同点:
1、Enumeration的方法名称太长,Iterator方法名称较为简短
2、Iterator的功能更加强大一些,多了一个删除方法,运行在遍历的同时进行删除操作
结论:Iterator是用于替换Enumeration的
多线程-线程状态 【重点】
NEW:新建
RUNNABLE:就绪
BLOCKED:阻塞
WAITING:无限等待
TIMED_WAITING:计时等待
TERMINATED:终结/死亡
多线程-线程池
什么是线程池
用于存储和管理线程的容器
池的好处
1、可以提高资源的重复利用 / 资源复用
2、可以提高响应速度
3、方便统一管理
Java已经有了现成的线程池的技术,我们只要能使用即可。
如何使用?
步骤:
1、获取/创建线程池对象
2、提交任务
// 3、关闭线程池
获取/创建线程池对象
获取
Executors:可以认为是一个用于获取线程池对象的工具类
ExecutorService/ThreadPoolExecutor:可以认为是线程池对象
Executors类
static ExecutorService newCachedThreadPool():常见一个默认线程数量为0的线程池
static ExecutorService newFixedThreadPool(int nThreads)
ExecutorService接口
<T> Future<T> submit(Callable<T> task)
Future<?> submit(Runnable task)
void shutdown()
创建
ThreadPoolExecutor类
是ExecutorService接口的实现类
* 构造方法
ThreadPoolExecutor(
int corePoolSize, -- 核心线程数量
int maximumPoolSize, -- 最大线程数量
long keepAliveTime, -- 时间值
TimeUnit unit, -- 时间单位
BlockingQueue<Runnable> workQueue, -- 任务队列,用于装任务的,类似排队的客户
ThreadFactory threadFactory, -- 线程池中线程怎么来的
RejectedExecutionHandler handler -- 拒绝策略
)
拒绝策略:
ThreadPoolExecutor.AbortPolicy 默认的,抛出RejectedExecutionException,并舍弃任务
ThreadPoolExecutor.DiscardOldestPolicy:丢弃任务,但是不抛出异常 这是不推荐的做法。
ThreadPoolExecutor.CallerRunsPolicy
ThreadPoolExecutor.DiscardPolicy
最大线程数量 = 核心线程数量 + 临时线程数量
核心线程:即使没有任务也不会消亡
临时线程:如果指定时间内没有任务则会消亡
能服务的最大任务数量 = 任务列队长度 + 最大线程数量
提交任务
关闭线程池
网络编程-相关概念
什么是网络编程
也可以称为Socket编程
在同一网络下,在通信协议的作用下,编写的程序可以实现不同的计算机之间的进行数据传输。
网络编程的三要素 【重点】
IP
设备在网络中唯一标识
分类:
IPV4
4个字节组成(总共32个二进制位),为了方便书写和记忆,使用“点分十进制法”进行表示
使用点分成4段,每一段占1个字节,每一段转成十进制最大为值255
255.255.255.255
IPV6
16个字节组成(总共128个二进制位),为了方便书写和记忆,使用“冒分十六进制法”进行表示
使用冒号分成8段,每一段占2个字节
端口
协议