--- 多线程编程 基本用法 java ---
随着时代的发展,单核cpu的发展遇到了瓶颈,而要提高算力就要发展多核cpu,他能允许多个程序同时运行,这时并发编程他能利用到多核的优势,于是就成为了时代所趋了
其实多进程编程也能进行实现并发编程,只不过进程太重了,每次创建和销毁所用的资源很大,于是在进程的基础上引入了线程,线程可以理解是轻量级的进程,他创建和销毁的速度更快,调度的速度也更快
对于他俩的区别
进程是系统申请资源的最小单位,线程是系统调度的最小单位
也就说,在申请资源的时候,是按进程来进行分配的,最小也不会小于一个进程需要的最少的数量,而线程是在进程之中的,他们共享进程的资源,并且在实际指令的执行也是通过线程来执行的而不是进程,进程出钱,线程出力,
一个进程中至少有一个进程,也就是主线程,他是程序入口
进程和进程之间是不会共享空间的,而线程和线程之间共享进程的空间
线程的创建
操作系统提供了一些线程的api来我们使用,java又对这些api进行封装到了Thread类中
通过继承thread类来创建线程
重写run方法,线程启动后运行的是run方法中的代码
在创建对象时重写run方法
使用lambda表达式
实现runnable接口来创建线程
线程的启动,需要调用start方法来启动,这样才会这和这个线程分配资源,若是调用run的话,他只是运行这个方法,并不会创建程序
前台线程和后台线程
当所有的前台线程都运行完毕之后,这个进程也就结束了,而这时即使后台线程还在运行也会结束他的运行,前台线程一般是和用户交互的线程,而后台线程不直接参与用户的交互,比如垃圾回收(gc),数据下载
将线程设为后台线程可以使用setDaemon方法
俩个线程都是后台线程,当这里唯一的前台线程main这个主线程运行完之后,就会结束进程,后台线程也会跟着结束
中断一个线程
当线程的入口方法(run)执行完之后,这个线程也就结束了,那么我想要中断这个线程,也就是让他直接return返回,这样run方法也就执行完了,那么如何让程序知道我执行了中断线程的操作呢,这时就可以使用interrupt方法,但线程处于阻塞状态时,调用interrupt方法会是线程抛出InterruptedException这个异常,使用try catch来捕捉这个异常,这样就知道了要中断这个线程
不过要注意的是当这个线程没有处于阻塞状态的话,是不会抛出这个异常的
也可以使用isInterrupted这个方法来判断是否打断
变量捕获
在线程中使用外部的局部变量的话会有风险,比如但我创建好了线程,并使用了外部变量a这时我的main函数执行完毕,a变量被销毁了,这时我在线程中还对这个变量进行了更改,那这肯定会出错,使用了一个不存在的变量,于是为了避免这样的事在java中的做法是在线程中拷贝一份这个变量,于是外面的变量是什么状况就和我无关了,然而还有情况,如果在线程中将这个变量更改了,但是外面有没改,这样一边改了,一边又没改,这就又会出错,于是在设计时决定,
在线程中调用外界的局部变量不能够更改,只能使用
等待一个线程 join
线程的调度是随机的,而如果先要的呢给某个线程先执行完了之后才使用另一个线程的话,可以使用join方法,当调用join方法后,可以理解为将run方法插入到调用join那个位置来执行,这时主线程就是在运行run方法
如果把t1的join放到了t2.start的下面的话,那么就不能决定t1 t2执行的先后顺序了,因为这是t2线程也被创建了,他的调度是由内核决定的,而我们的编程是在应用程序上的,并不能决定操作系统内核的事
这里没有给join设置最长等待时间,这就以为这会无限的等待下去知道t1线程执行完毕,这不是很科学,可以给join传参来设值main函数的最大阻塞时间,在这个时间过了之后就会继续向下执行代码
下一篇 线程安全及其解决方案
end~~~