多线程(三种实现方式&守护线程&礼让线程&插入线程)
一:什么是多线程?
多线程可以拆开理解,“多”是一个数量词,表示很多的意思,所有我们只要知道什么是线程就可以了。
(1)进程:程序的基本执行实体
举个例子:比如打开任务管理器,在任务管理器的第一个界面中就是进程。看下面每一个软件都对应着一个进程。所以说什么是进程?一个软件运行之后他就是一个进程,比如Typora的进程,画图板的进程。
(2)线程:线程是操作系统能够就行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
举个例子:比如有一个软件叫做360,在360里面有很多很多独立的功能的,比如“木马查杀”,“电脑清理”等等。我们可以这样去理解:360这个软件运行之后,它的本身是一个进程,而里面的“木马查杀”,“电脑清理”等等我们就可以把他们看做是多个线程。所以线程可以简单理解为:应用软件中互相独立,可以同时运行的功能。如果说这些互相独立,可以同时运行的功能比较多,就形成了多线程。
(3)为什么有多线程呢?
小白要去工厂打螺丝,小白负责一条流水线上面的工作,工作的内容就是把流水线上的货物拿下来堆放在一起。但是流水线上的货物不是连续的,假设每件货物的间隔时间是十分钟,小白是不是搬了一个货物之后就可以摸鱼十分钟?但是老板心里不爽了,所以老板就让小白同时负责两条流水线的工作。是还可以给小白加第三条,第四条等等。小白一会儿干这条,一会儿干那条,此时是一个人同时负责多条流水线,工作的效率就得到了提高。小白为什么可以同时操作多条流水线,提高工作效率呢?他就是把货物间隔的可以用来摸鱼的时间充分利用起来了,这样小白才能在多条流水线之间进行切换,这样才能提高工作效率。
我们的代码是不是类似的呢?看下面的程序
int a = 10;
int b = 20;
int c = a + b;
System.out.println(c);
分析一下过程:在运行的时候,CPU首先是读到了第一行代码,那么在内存当中就会创建一个变量a,但是内存当中创建变量是需要时间的!!虽然这个时间很短很快,但是也是要时间。那么在创建的过程中,CPU他是没有办法继续运行下面的代码的,所以CPU只能先等着。假设CPU等了0.01秒,然后再去读第二行,内存当中再去创建一个变量b,同样也等了0.01秒。同理第三行也等了0.01秒。第四行也等了0.01秒。这就是我们以前代码的执行过程,以前的代码我们也叫做单线程程序,因为他是从头往下依次运行的,和刚刚故事中的一条流水线是一样的。CPU不会切换到其他代码中去运行,所以效率比较低。
那么多线程是怎么样的?看下面的程序
int[] arr = {
1, 2, 3, 4, 5, 6, 7, 8, 9};
int max = arr[0];
for(int i = 1, i < arr.length, i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println(max);
多线程程序的特点就是能同时的去做多件事情,CPU可以在多个程序之间进行切换,把等待的空闲时间充分的利用起来,这就是多线程最大的特点,提高程序的运行效率。
(4)多线程的应用场景
1、软件中的耗时操作
2、拷贝、迁移大文件
3、加载大量资源文件
4、所有的聊天软件
5、所有的后台服务器
(5)总结
1、什么是多线程?
有了多线程,我们就可以让程序同时做多件事情
2、多线程的作用?
提高效率
3、多线程的应用场景?
只要你想让多个事情同时运行就需要用到多线程。
比如:软件中的耗时操作,所有的聊天软件,所有的服务器。
二:并发和并行?
(1)并发:在同一时刻,有多个指令在单个CPU上交替执行
解释:并发重点强调“交替”,就好比平时打游戏,还要抽烟喝可乐。于是你的右手一会儿摸摸鼠标,一会儿拿跟烟,一会儿喝一口可乐。此时由于你的手速非常快,他是在多个物品中交替执行的,所以这种情况我们就可以把它看做是并发。你的右手好比是CPU,鼠标,烟,可乐好比是线程,你的手在这三个线程之间来回切换,这就是并发。
(2)在同一时刻,有多个指令在多个CPU上同时执行
解释:并行重点强调“同时”,好比是两个线程,两个CPU同时执行。
疑问:什么两个CPU?哥们电脑不就一个CPU吗?
是的没错。但是CPU他是有二核四线程、四核八线程、八核十六线程…等等。而这里线程的数量就表示你的电脑能同时运行多少条线程。
以二核四线程为例:他是可以同时并行四条线程的,所以如果你的计算机当中只有四条线程,那么他是不用切换的。但是如果你的线程越来越多,那么这四个线程就会在多个线程之间“随机”的进行切换。所以在外面的计算机当中,并发还有并行是有可能同时都在发生的。
(3)总结
1、并发:在同一时刻,有多个指令在单个CPU上交替执行
2、在同一时刻,有多个指令在多个CPU上同时执行
三:多线程的第一种实现方式
(1)继承Thread类的方式进行实现
看API帮助文档查询的Thread这个类:线程是程序当中的执行线程,Java虚拟机允许应用程序并发地执行多个执行线程。
什么意思?就是说这个Thread类,他就表示我们Java里面的一个线程。如果说你想拥有一条线程,那么就可以创建他的对象并开启他就可以了。
public class ThreadDemo {
public static void main(String[] args) {
/*
* 多线程的第一种启动方式:
* 1.自己定义同一个类继承Thread
* 2.重写run方法
* 3.创建子类的对象,并启动线程
* */
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.setName("线程1");
t2.setName("线程2");
// 不能这样写,这样写仅仅是调用方法。应该调用start方法开启线程
// t1.run();
// 开启线程
t1.start();
t2.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
// 书写线程要执行的代码
for (int i = 0; i < 100; i++) {
System.out.println(getName() + "HelloWorld"