一、概念
进程:正在进行中的程序(直译),是静态的概念。程序执行时,内存会为其分配空间。
线程:通俗的讲,线程就是一个程序中的不同执行路径。换句话说,进程中负责程序执行的控制单元(执行路径)就是线程。
一个进程中可以有多个执行路径,我们称之为多线程。一个进程中至少有一个线程,因为进程是静态的概念,不能执行,
它只负责从内存中分配空间,执行的过程由线程完成。
为什么要开启多线程呢?
程序中需要执行耗时任务时,如果只有一个线程,要一直等到耗时任务结束才可以继续执行下面的代码,比较耗时。如果开启一个
专门执行耗时任务的线程,执行耗时任务时就不需要等待,主线程可以继续干自己想干的事。所以开启多线程是为了能够同时运行多部分的代码。
每个线程都有自己的运行内容,这个内容称之为任务,即线程要执行的任务。
应用程序的执行都是CPU在做着快速切换完成的,一个CPU在同一时间点上只能执行一个线程。且切换时随机的。所以当开启多个线程时,每个线程
分到的时间片的概率就降低了,会降低运行效率。
开启多线程的好处和坏处:
好处:解决了多部分代码,多个功能块同时运行的问题
坏处:线程太多会降低效率
Java虚拟机启动时开启了几个线程呢?
JVM启动时开启了多个线程,至少有两个是可以分析出来的
1.执行main函数的线程
2.处理垃圾回收的线程
为什么呢?
我们说了,创建线程的目的就是为了开启一条执行路径,去运行指定的代码和其他代码实现同时运行的效果,而
运行的指定代码就是执行路径的任务。而JVM创建的主线程的任务(执行代码)都定义在main函数中,在main函数中执行代码时
内存会为其分配资源,main函数执行完了以后,资源要被释放,释放资源就要用到垃圾回收器,垃圾回收器实质上也是一个处理垃圾
回收的线程。
二、线程的创建
既然主线程的任务都定义在主函数中,那么自定义的线程的任务又定义在哪呢?
Thread 用户描述线程,而线程是需要任务的,所以Thread类也对任务描述。Thread类中有一个run方法,
run方法中定义的就是线程要执行的任务代码,开启线程是为了运行指定的代码,
所以只有继承Thread类 并且重写其run方法,将指定的运行代码定义在run方法中即可。
创建线程方式一:继承Thread类
步骤:
1.定义一个类继承Thread类
2.重写Thread类的run方法
3.直接创建Thread子类的对象创建线程
4.调用Thread类的start方法启动线程
线程启动之后,会自动调用run方法执行线程。那么问题来了,直接调用run方法和调用start方法有 什么区别呢?
直接调用run方法就是一个普通的方法调用,并没有在主线程中开启另外一个线程
而调用start方法是启动了一个新的进程
当同时执行多个子线程时,我们如何区分正在执行的是哪个线程呢?
同时执行多个子线程时,我们可以通过Thread类的currentThread()方法获取当前在执行的是哪一个线程,
然后调用getName()方法获取当前正在执行的线程名称,即可区分出当前执行的是哪个线程。
创建线程方式二:实现Runnable接口
步骤:
1.定义一个类实现Runnable接口
2.重写Runnable接口中的run方法(线程的任务代码封装在run方法中)
3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数参数传递给
Thread对象。为什么呢? 因为线程的任务都封装在Runnable接口子类对象的run方法中,Thread对象
中没有任务,而每个线程都必须要有任务,所以要在线程对象创建时就必须明确要运行的任务。
4.调用Thread类的start方法启动线程