多线程
1.进程:当前正在执行的程序。
代表一个应用程序在内存中的执行区域。
线程:是进程中的一个执行控制单元,执行路径。
一个进程中至少有一个线程在负责控制程序的执行。
一个进程中如果只有一个执行路径,这个程序称为单线程。
一个进程中有多个执行路径时,这个程序成为多线程。
2.多线程的出现:可以有多条执行路径,让多部分代码可以完成同时执行。
以提高效率。本身也是对问题的一种解决方案。
比如:图形界面中的多个小程序的同时执行,例子:360管理软件。
3.JVM启动是单线程,还是多线程的呢?
jvm的启动其实就是多线程程序。
其中有一个程序负责从主函数开始执行,并控制程序运行的流程。
同时为了提高效率,还启动了另一个控制单元(执行路径)专门负责堆内存中的垃圾回收。
在程序正常执行过程中,如果出现了垃圾,这是另一个负责收垃圾的线程会在不定时的时间进行垃圾的处理。
这两个程序是同时执行的。
负责执行正常代码的线程,称为主线程。该线程执行的代码都存放于主函数中。
负责收垃圾代码执行的线程,成为垃圾回收线程。该线程要执行的代码在finalize中。
那如何创建一个线程呢?
其实Java中对线程这类事物已经进行了描述,并提供了相对应的对象。
这个对象就是Thread。
通过API查阅,发现Thread类描述时,有两种创建线程的方式。
方式一:定义一个类继承Thread类,并覆盖Thread类中run方法。
作为了解掌握:
为什么要继承Thread,为什么要覆盖run
其实直接建立Thread类对象即可。并开启线程执行就可以了。
但是虽然线程执行了,可是执行的代码是该线程默认的代码,该代码就存放在run方法中。
可是定义线程的目的是为了执行自定义的代码。
而线程运行代码都存储在run方法中,所以只有覆盖了run方法,才可以运行自定义的内容,想要覆盖,必须先要继承。
主线程运行的代码都在main函数中,
自定义线程运行的代码都在run方法中。
线程中的几个方法。
多线程的创建,为了对各个线程进行标识,他们有一个自己默认的名称。
格式:Thread-编号,编号从0开始。
static Thread currentThread():获取当前线程对象。
String getName():获取线程名称。
void setName():设置 线程的名称。
Thread(String name):构造函数,线程对象一建立就可以指定名称。
创建线程的两种方式:
1,继承Thread类。
步骤:
1,定义类继承Thread。
2,覆盖Thread类中的run方法,run方法用于存储多线程要运行的代码。
3,创建Thread类的子类对象创建线程。
4,调用Thread类中的start方法开启线程,并执行子类中的run方法。
特点:
1.当类去描述事物,事物中有属性和行为。
如果行为中有部分代码需要被多线程所执行,同时还在操作属性。
就需要该类继承Thread类,产生该类的对象作为线程对象。
可是这样做会导致每一个对象中都存储一份属性数据。
无法在多个线程中共享该数据。加上静态,虽然实现了共享但是生命周期过长。
2.如果一个类明确了自己的父类,那么很遗憾,它就不可以在继承Thread。
因为java不允许类的多继承。
2,实现Runnable接口:
步骤:
1,定义类实现Runnable接口。
2,覆盖接口中的run方法,将多线程要运行的代码定义在方法中。
3,通过Thread类创建线程对象,并将实现了Runnable接口的子类对象
作为实际参数传递给Thread类的构造函数。
为什么非要被Runnable接口的子类对象传递给Thread类的构造函数呢?
是因为线程对象在建立时,必须要明确自己要运行的run方法,而这个run方法
定义在了Runnable接口的子类中,所以要将该run方法所属的对象传递给Thread类的构造函数。
让线程对象一建立,就知道运行哪个run方法。
4,调用Thread类中的start方法,开启线程,并执行Runanble接口子类中的run方法。
特点:
1.描述事物的类中封装了属性和行为,如果有部分代码需要被多线程所执行。
同时还在操作属性。那么可以通过实现Runnable接口的方式。
因为该方式是定义一个Runnable接口的子类对象,可以被多个线程所操作
实现了数据的共享。
2.实现了Runnable接口的好处,避免了单继承的局限性。
也就说,一个类如果已经有了自己的父类是不可以继承Thread类的。
但是该类中还有需要被多线程执行的代码。这时就可以通过在该类上功能扩展的形式。
实现一个Runnable接口。
所以在创建线程时,建议使用第二种方式。