Java线程创建与运行全解析
目录
一、Java程序的运行
1.启动过程
2.线程任务
二、线程的创建
1.Thread子类重写
1.1子类线程直接执行
1.2父类线程重写执行
1.2.1向上转型
意义
1.2.2匿名类
场景
(1)向上转型
(2)临时针对
2.Runnable实现类重写
三、线程的属性
1.优先级
2.存活
3.前台线程
一、Java程序的运行
1.启动过程
(1)Java程序启动时,操作系统会为此Java程序 创建一个JVM进程来运行
(2)JVM进程 创建并启动 主线程main,从主线程的入口方法main() 开始执行
2.线程任务
每个线程启动后 以执行完入口方法为准地 自动调用去执行run方法
- thread.start() 启动->调用 thread.run()
二、线程的创建
创建线程时,原生线程对象的 入口方法run() 是选择性空逻辑,需要多态地 重新自实现出一个run()方法 并执行它,无法在Thread类源码那边 直接修改成自己的run逻辑,得在 往下扩展的 Thread子类或Runnable实现类中 重写自实现run
链接:重写详解
1.Thread子类重写
创建 Thread类的 子类线程后,在直接子类线程或转型父类线程 都能执行 自实现的run方法
1.1子类线程直接执行
子类线程 继承可调用 父类的start(),在子类线程里 重写自实现出run方法后,start启动子类线程 便调用执行子类线程里面 自实现的run方法了(父子相同的run方法,子类优先调用)
1.2父类线程重写执行
子类线程 赋值向上转型 成父类线程后,父类线程 启动调用 也不管target是否为空 会重写 向下转 回执行 子类线程自实现的run方法
1.2.1向上转型
子类线程 继承原生线程 自实现出run方法逻辑后,其实就可直接启动子类线程 直接调用执行 子类线程已自实现的run逻辑了,但常常将子类线程 赋值向上转型成 统一的父类原生线程,启动原生线程来调用run 再往下重写转回执行 子类线程重写的自实现run
意义
父类 可以无限制地 向下继承出 千姿百态的子类、创建出 各种各样的子类实例
将子类实例 全部各自 赋值向上转型成 统一父类的实例,各种各样的子类实例 就可以靠赋值对应关系 全部统一用简单的父类模式又对应各自效果地 简单统一又多态效果地管理了
1.2.2匿名类
匿名类 省去跳过 类的单独创建,使用匿名方式 快速一次性创建 继承子类、实现接口的 扩展类实例
- 匿名类实现只有一个抽象方法的接口 还可以化简成Lambda表达式 来创建实例
链接:匿名类详解
链接: Lambda表达式详解
场景
(1)向上转型
将子类实例 赋值向上转型成 用父类实例管理后,父类调用使用时 具体重写转化到哪个子类、子类方法具体如何实现的细节 都可以不用知道,只需要了解使用 转成的简单父类层面,以后都不会主动用到子类的
(2)临时针对
继承的子类的 类类型 就是只使用一次 来临时创建子类实例 只针对这种情况使用的,以后再也不会有 重复使用此类的需求
class ChildThread extends Thread{@Overridepublic void run() {//run自实现内容}
}
class Test1 {public static void main(String[] args) {//1.用定义的Thread子类ChildThread 实例创建Thread thread1 = new ChildThread();thread1.start();//2.用扩展继承Thread的匿名子类 实例创建Thread thread2 = new Thread() {@Overridepublic void run() {//run自实现内容}};thread2.start();}
}
2.Runnable实现类重写
可以创建Thread类 原生线程,传入 里面已重写自实现run方法的 Runnable接口实现类实例,赋值向上转型成 Runnable接口类型的 target变量,start启动Thread类线程时 调用原生线程的run方法,target不为空 选择调用 已向上转型target接口变量的 run方法,即会向下重写 转到执行 Runnable实现类里面 自实现的run方法
(原生父类Thread的构造方法 里面都还可额外传入 String字符串 作为线程的名字)
class ChildRunnable implements Runnable{@Overridepublic void run() {//run自实现内容}
}
class Test2 {public static void main(String[] args) {//1.用定义的Runnable实现类ChildRunnable 实例创建 Runnable的实现类实例Thread thread1 = new Thread(new ChildRunnable());thread1.start();//2.1用扩展实现Runnable接口的匿名子类 实例创建Thread thread2 = new Thread(new Runnable() {@Overridepublic void run() {//run自实现内容}});//2.2Lambda表达式化简2.1Thread thread3 = new Thread(()->{//run自实现内容});}
}
三、线程的属性
属性 | 获取方法 |
ID | getId() |
名称 | getName() |
状态 | getState() |
优先级 | getPriority() |
是否后台线程 | isDaemon() |
是否存活 | isAlive() |
是否被中断 | isInterrupted() |
链接:线程详解
1.优先级
操作系统 按由系统调度器具体实现决定的 即使有一定优先级分配 但也无法固定概率的 随机顺序 对已启动线程进行调度
2.存活
run执行结束,操作系统内核里的该线程 也就销毁死亡了,Thread对象的生命周期 比对应线程的生命 更长一些,可以获取 所对应线程 是否存活的信息
3.前台线程
前台线程是否还有存活 决定整个进程的结束,线程默认是前台线程