线程类以及创建多线程的第一种方式---继承Thread类
先来看一个例子理解主线程和单线程:
/* 主线程:执行主(main)方法的线程 单线程程序:Java程序中只有一个线程 程序从main方法开始,从上到下依次执行 */ public class Demo11MainThread { public static void main(String[] args) { Person p1 = new Person("易烊千玺",18); Person p2 = new Person("王俊凯",19); p1.run(); p2.run(); } }
过程:
首先JVM执行应用程序,main方法,从方法区进入到栈中,JVM会找操作系统开辟一条main方法通向cpu的执行路径(线程),然后cpu就可以通过这个路径来执行main方法,这个路径名字就是主线程。
单线程弊端:由于是从上到下依次执行,中间有环节出现异常的时候,后面的任务也会终止,因此引入多线程的使用。
创建线程类:
Java使用java.lang.Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例,每个线程的作用是完成一定的任务,实际上就是执行一段程序即一段顺利执行的代码。Java使用线程执行体来代表这段程序流。
Java创建多线程有两种方式:
第一种:Java中通过继承Thread类来创建并启动多线程的步骤如下:
1.定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把run()方法称为线程执行体。
2.创建Thread子类的实例,即创建了线程对象
3.调用线程对象的start()方法来启动该线程
void |
|
结果是两个线程并发地运行;当前线程(main线程)和另一个线程(创建的新线程,执行其 run
方法):
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。
Java程序属于抢占式调度,哪个线程的优先级高,就先执行,优先级相同,就随机选择一个执行。
/* 线程类的子类,重写run()方法 */ public class MyThread extends Thread{ // 1.定义Thread类的子类,并重写该类的run()方法 @Override public void run() { // super.run(); for (int i = 0; i < 20; i++) { System.out.println("run" + i); } } }
public class Demo11Thread { public static void main(String[] args) { // 并发运行的第一个线程 // 2.创建Thread类的子类对象 MyThread mt = new MyThread(); // 调用Thread类中的方法start方法,开启新的线程,执行run()方法 mt.start(); // 开启新的(第二个线程) for (int i = 0; i < 20; i++) { // 主线程的代码块 System.out.println("main" + i); } } }
执行结果:
从结果可以看出来,Java采用抢占式调度,优先级相同,随机选择执行。
多线程运行原理
以上述代码举例,解释多线程程序的执行流程:
多线程内存图解:
main方法压栈执行,new的对象在堆内存中分配一块空间,并将内存地址值赋值给相应变量mt,执行mt.run(),方法压栈运行(此时为单线程,是对象调用方法,而不是创建新的线程),运行到mt.start()时,并不是方法压栈执行,而是开辟一个新的栈空间。