什么是线程:
进程是指可执行程序并存放在计算机存储器的一个指令序列,它是一个动态执行的过程
我们打开Windows任务管理器
看到进程选项卡,比如qq和记事本
有的软件对应一个进程,有的软件对应多个进程,比如杀毒软件或者数据库软件
比较大的软件是多个进程组成的
早期的操作系统都是单任务的操作系统,也就是我们看到的QQ或者音乐播放器,只能一个运行。一个运行结束才能进行下一个程序的运行,必须先听歌曲这歌听完了才能回复好友问题。
现在操作系统都是多任务操作系统,可以多个程序同时运行。
线程:线程是比进程还要小的运行单位,一个进程包含多个线程
其实就是一个进程可以包含多个线程,比如说一个程序,由很多行代码组成,那么这有些代码就可以分成很多块,放到不同的线程当中去分别执行,所以我们认为线程可以看做一个子程序。
程序的运行是靠CPU来处理,那如果只有一个CPU的情况下怎么能保证这些程序都能同时运行?
我们可以想象成把CPU的执行时间分成很多小块,每一小块的时间都是固定的,我们可以把这一个小块叫做时间片,时间片的时间可以非常短,比如说1ms。
如果我们有音乐播放器,代码编辑器,QQ三个软件同时运行,那么他们三个怎么获取CPU的执行时间呢?
这个其实是随机的,我们可以这么考虑,我们音乐播放器运行1ms然后就会把CPU的使用权转给代码编辑器,代码编辑器运行1ms又将使用权转给QQ,那么这些程序就轮流的在很短的时间使用我们的CPU,对CPU来讲这些软件其实是轮流运行的。但是它运行的时间间隔非常的短,所以我们使用者是感觉不到它的变化的。所以我们就能认为这些软件都是同时运行的。
这个就是时间片的轮转,是通过对CPU时间的轮转来达到同时运行的效果。
线程的创建:
有两种方式
1 创建一个Thread类,或者一个Thread子类的对象
2 创建一个实现Runnable接口的类的对象
Thread是一个线程类,位于java.lang包下
Thread类的常用方法
第一个最重要的方法run,不同功能线程之间他们之间的区别就在于run方法中的代码是不相同的,我们可以把run方法中的代码叫做线程体的代码
join方法:字面上是加入,其实是抢占资源
Runnable接口
只有一个方法run();
Runnable是Java中用以实现线程的接口
任何实现线程功能的类都必须实现该接口
Thread定义形式
创建自定义线程
创建并启动线程
创建线程:
1.通过继承Thread类方式创建线程,重写run()方法
注意启动线程不是run方法,启动线程执行的时候还是run方法里的代码
一个线程只能启动一次
当前其实是由两个线程在运行的,另一个是主方法本身他就是一个线程,或者说主线程
当前其实是主线程和mt两个线程在运行
发现和以前的普通方法不同,以前是从上往下一次执行
因为这个线程是随机的,这个线程什么时候获得CPU使用权是不好判断的
后面如果多写代码包含循环的时候就更明显了,就是随机的
还有一点线程是不能多次启动的,只能调用一次start()方法
抛出了异常
我们看下运行情况
先是线程1运行10次,再是线程2运行10次
在运行一次发现线程2运行,再是线程1运行
再来一次
这次完全混乱了
整个运行都是随机的,线程想要获得CPU使用权其实是随机的
Runnable接口方式创建线程
为什么要实现Runnable接口?
1.Java不支持多继承,如果你的Class类继承了一个类,再去继承Thread类是不可以的。接口可以实现多个接口
2.不打算重写Thread类的其他方法,如果继承这个类就会继承Thread类所有方法,对线程来说只要重写run()方法就可以了
注意和thread类的区别,要三步
注意如果是成员变量就会随机了
因为这个代码可以被多个线程共享,多个现场是Thread类实例
多个线程共享一个资源
我们的i相当是一个资源我们的两个线程共享资源
线程的状态:
1 新建(New)
2 可运行(Runable)
3 正在运行(Running)
4 阻塞(Blocked)
5 终止(Dead)
线程的生命周期:
就是5个状态的转换过程
如上图,不过stop()方法不建议使用
sleep()方法
它是Thread类方法
作用:在指定的毫秒数内让正在执行的线程休眠(暂停执行)
不过一般需要捕获异常,因为会打断之类的异常
我们可以用来计时,和定期刷新数据
这样会交替运行
jion方法
Thread类方法:
作用:等待调用该方法的线程结束后才能执行
我们发现主线程永远是最后运行结束的
这样线程会有先后顺序执行
jion()方法抢占资源
作用:等待该线程终止的最长时间为millis毫秒
线程的优先级:
Java为线程提供了10个优先级
优先级可以用整数1-10表示,超出范围会抛异常
主线程默认优先级为5
数字越大,优先级越高
优先级常量:
MAX_PRIORITY:线程的最高优先级10
MIN_PRIORITY:线程的最低优先级1
NORM_PRIORITY:线程的默认优先级5
优先级相关方法:
我们发现是5
优先级也是有随机性的
不能完全保证优先级高的一定先执行
多线程的运行问题:
各个线程是通过竞争CPU时间而获得运行机会的
各线程什么时候得到CPU时间,占用多久,是不可预测的
一个正在运行着的线程在什么地方被暂停是不确定的
线程同步:
我们需要将对象进行锁定
锁定关键字synchronized实现
同步关键字
关键字用在:成员方法 静态方法 语句块
执行期间其他代码不允许打断的
线程间的通信:
wait()方法:终端方法的执行,使线程等待
容易死锁
notify()方法:唤醒处于等待的某一线程,使其结束等待
notifyAll()方法:唤醒所有处于等待的线程,使其结束等待
我们利用flag来看是否等待,和唤醒(不唤醒会死锁)