多线程
Posted macht
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程相关的知识,希望对你有一定的参考价值。
进程接口Runnable是一个函数式接口,它的子类有Thread和任何实现它的类。但是由于它是一个函数式接口想要启动必须借助Thread的start方法,因此这里就用到了装饰器模式。把用户实现的Runnable类放入Thread方内部就能在不改变原对象代码的基础上给他扩展出start方法。
线程相关概念
进程和线程
- 进程:正在运行的程序,一旦程序启动,操作系统就会为进程分配系统资源(内存、CPU),一个软件可能有一个或多个进程。
线程:一个进程可能需要执行多个任务,多个任务的执行需要同时运行,相互不影响,每个任务由一个线程执行,一个进程可能包含一个或多个线程。
进程和线程的区别:
- 一个进程包含多个线程
- 进程属于重量级单位,线程属于轻量级单位
进程的创建、启动、销毁需要更多的系统资源,比较复杂
线程相对来说占用资源更少,更容易使用
线程间通信比进程间容易,快速 进程之间是相互独立,多个线程可以共享所在进程的堆内存,每个线程有独立的栈和寄存器
多进程和多线程:
多进程就是多个进程同时执行,现代操作系统是多进程的,一个CPU一个时间点只能运行一个进程,CPU需要在多个进程间来回切换,因为CPU速度快,所以用户感觉多个进程同时执行。
多线程是一个进程的多个任务,CPU执行进程时,会在多个任务之间来回切换,会给每个任务一定执行时间(CPU时间片),线程就是CPU分配时间片的单位。
同步和异步
- 同步
单线程执行,多个任务需要排队执行
类似:银行的排队 - 异步
多线程执行,启动另一个线程执行任务,当前线程执行其他任务,另一个线程执行完后通知当前线程
类似:找另一个人去银行办业务,自己做别的事情
并行和并发
- 并行
多个CPU,每个CPU执行一个线程,同时执行一个任务 并发
一个CPU在多个线程间切换,不是真正同时执行多个任务线程应用场景
企业级应用:大量用户进行同时访问,服务器会为每个用户开辟新线程,每个用户操作时就不会相互影响。
游戏开发:网络通信、图形绘制、运动控制都需要线程单独执行
Java线程的实现
继承Thread类,重写run方法
执行线程,调用start方法
1)定义类继承Thread
2)重写run方法
3)创建线程对象,调用start
面试题:执行start和run有什么区别?
只有执行start,操作系统才创建新的线程,执行任务,run还是在主线程执行任务,没有新线程,注意:不要手动调用run方法!!实现Runnable接口,重写run方法
1)定义类实现Runnable接口
2)实现run方法
3)创建Thread对象,传入Runnable对象
4)调用start方法面试题:继承Thread和实现Runnable哪个好?
1) 继承Thread类就不能继承其他类,实现Runnable没有此限制
2)实现Runnable强制要求重写run,继承Thread不要求容易出错
线程的启动和停止
- 启动必须调用start方法
- 如何停止?
1)调用stop方法,执行stop后不会释放锁,可能导致死锁(禁用)
2)等待run执行完
3)在run中加入条件,终止run的执行
线程的执行过程
多线程的执行是抢占式的,每个线程可能在执行中间,就被其他线程抢占CPU执行,线程会来回抢占CPU。
线程的优先级
可以控制CPU给线程分配时间片的概率
线程的方法:
setPriority(int priority)
优先级从低到高1~10,默认是5
开发过程中给任务重要的线程分配更高优先级,让该线程优先完成
线程的生命周期
类似人的生老病死,线程也有自己的生命周期
- 新建
创建了线程对象,没有调用start方法 - 准备
线程调用了start方法,CPU还没有分配时间片 - 运行
线程获得时间片,正在执行run方法 - 阻塞
进入阻塞的情况:
1. 进行IO操作
2. 进入睡眠 sleep
3. 进入挂起 suspend
4. 进入等待 wait
从阻塞状态恢复:
1. IO操作完毕
2. 睡眠时间结束
3. 执行恢复 resume
4. 被通知 notify - 死亡
run执行完毕
使用多线程实现聊天程序
单线程中IO会产生阻塞,读写不能同时执行,读写操作必须分别放到不同线程中才能同时执行。
线程的睡眠
可以让当前线程进入睡眠状态
Thread.sleep(毫秒数)
后台线程
也叫守护线程(精灵线程)
一种特殊的线程,为其他线程提供服务,一旦其他线程都死亡了,守护线程会自动死亡。一个典型的守护线程就是GC(垃圾收集器)
方法:
setDaemon(boolean b) true 守护线程,false 非守护线程 (默认)
必须在start之前调用
线程的合并
一个线程可以在执行时合并另一个线程,让另一个线程完成执行完,自己再执行。
run(){
另一个线程.join()
}
注意:两个线程之间不能相互合并,否则可能出现死锁情况
作业:
- 完成聊天案例
- 设计两个线程,一个线程负责求出1~100以内所有的偶数;然后,另外一个线程负责打印1~100以内所有的奇数。
测试时,分别设置线程的优先级,观察执行的顺序。 - 同时启动2个线程,一个用于扫描某个目录下的所有文本文件(包括:java、txt、html),并将文字内容打印出来,一个收集磁盘上所有的图片文件复制到C:images目录下。
- 某人正在看电视连续剧,从第1~88集,看到第10集时,来了一个送快递的,收完快递后后,继续看电视。(线程的合并,join)
- 多线程模拟龟兔赛跑:
乌龟和兔子进行1000米赛跑,兔子前进5米,乌龟只能前进1米。
但兔子每20米要休息500毫秒,而乌龟是每100米休息500毫秒。
谁先到终点就结束程序,并显示获胜方
以上是关于多线程的主要内容,如果未能解决你的问题,请参考以下文章