当前位置: 首页 > news >正文

【线程】Java多线程编程

【线程】Java多线程编程

      • 一、前言
        • 一个最简单的多线程编程示例
        • 可以使用的工具
      • 二、创建线程的方式
      • 三、Thread类中重要的属性和方法
        • 3.1 构造方法
        • 3.2 常见属性

一、前言

当有多个线程的时候,这些线程的执行顺序是不确定的。这一点,是我们之前提到的操作系统随即调度造成的。线程是系统调度的基本单位,进程是系统分配资源的基本单位。

什么叫做“随机调度”?

  1. 一个线程,什么时候被调度上CPU上执行,时机是不确定的;
  2. 一个线程,什么时候从CPU上下来,让其他线程上去,时机也是不确定的;
  3. 多个线程的执行顺序是不确定的。

所谓“随机调度”,我们可以将其理解为抢占式执行,即多个线程抢占CPU的使用权,但是谁抢到了,不确定。

一个最简单的多线程编程示例
public class ThreadDemo1 {public static void main(String[] args)  {MyThread t =new MyThread();t.start();while(true){System.out.println("hello world");}}
}class MyThread extends Thread{@Overridepublic void run() {while(true) {System.out.println("hello thread");}}
}

执行结果:
在这里插入图片描述
可以发现,hello threadhello world的执行顺序不确定,每次出现的次数也不确定(执行时间也不确定),这很好的印证了我们之前所说的随机调度或者是抢占式执行

可以使用的工具

Jdk中提供了一个工具Jconsole,可以用来观察线程的状态:
在这里插入图片描述
这就是我们刚才创建的两个线程Thread-0main,由于Java程序是运行在JVM虚拟机上的,JVM有一些垃圾回收、监控统计各种指标等功能,所以还存在一些别的线程。在这里插入图片描述

二、创建线程的方式

  1. 继承Thread类,重写run方法
class MyThread extends Thread{@Overridepublic void run() {System.out.println("hello");}
}public class ThreadDemo1 {public static void main(String[] args)  {MyThread t =new MyThread();t.start();}
}
  • Thread类实现了Runnable接口
  1. 实现Runnable接口,重写run方法
class MyThread implements Runnable{@Overridepublic void run() {System.out.println("hello");}
}public class ThreadDemo1 {public static void main(String[] args)  {Thread t =new Thread(new MyThread());t.start();}
}
  1. 继承Thread,重写run方法,使用匿名内部类
  • 匿名内部类,在一个类里面定义,写法简单,但没有名字,不能调用,只能使用一次。
public class ThreadDemo1 {public static void main(String[] args)  {//此处t指向的是Thread的子类,没有名字,故称为匿名内部类//匿名内部类内重写了run方法,实现一定的逻辑Thread t =new Thread(){@Overridepublic void run() {System.out.println("hello");}};t.start();}
}
  1. 实现Runnable接口,重写run方法,使用匿名内部类
public class ThreadDemo1  {public static void main(String[] args)  {Thread t=new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});t.start();}
}

5.λ表达式

public class ThreadDemo1  {public static void main(String[] args)  {Thread t=new Thread(()-> {System.out.println("hello");});t.start();}
}
  • λ表达式可以理解为是函数式的接口,不过这个函数也是匿名的
  • 如果要实现的逻辑比较简单,λ表达式是非常推荐使用的

其实λ表达式这种写法,相当于Runnable重写run方法。编译器在编译的时候,Thread构造方法有好几种,匹配到Runnable这个版本的时候,发现正好可以匹配上,而Runnable内部的run()没有参数,匹配到λ。(相当于是省略了方法名)

三、Thread类中重要的属性和方法

3.1 构造方法
构造方法说明
Thread()创建线程对象
Thread(Runnable target)使用实现了Runnable接口的对象创建线程对象
Thread(String name)创建线程对象,并命名
Thread(Runnable target,String name)使用实现了Runnable接口的对象创建线程对象,并命名
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("Just a name");
Thread t4 = new Thread(new MyRunnable(), "Just a name");
  • 如果没有命名,默认按照Thread-0,1,2,3的方式命名。
3.2 常见属性
属性获取方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程(守护线程)isDaemon()
是否存活isAlive()
是否被中断isInterrupted()
  1. 我们前面讲到进程的时候,说到进程有状态,比如就绪状态和阻塞状态,此处的线程也有状态,并且Java对线程的状态,进行了进一步的区分。
  2. 后台线程和前台线程的区别:前台线程的运行,会组织进程结束;后台线程的运行,不会阻止进程结束。默认创建前台线程。
public class ThreadDemo1  {public static void main(String[] args) throws InterruptedException {Thread t=new Thread() {@Overridepublic void run() {while (true) {System.out.println("hello");}}};//可以在线程启动前设置前台线程和后台线程t.setDaemon(true);//一个线程只能启动一次t.start();System.out.println("这是主线程,期望在t线程结束后打印");}
}
  1. 如何理解线程是否存活?
    简单的说,这里描述的是操作系统中这个线程是否被真正创建出来了。我们在代码中创建出线程对象后,此时系统中并没有真正创建出线程,需要我们调用start方法,系统中才能真正创建出线程,此时线程才是存活的。
public static void main(String[] args) throws InterruptedException {Thread t=new Thread(new Runnable() {@Overridepublic void run() {System.out.println("hello");}});System.out.println("线程启动前"+t.isAlive());t.start();System.out.println("线程运行中"+t.isAlive());Thread.sleep(1000);System.out.println("线程运行结束"+t.isAlive());}

运行结果:
在这里插入图片描述


http://www.mrgr.cn/news/77852.html

相关文章:

  • 瑞佑液晶控制芯片RA6807系列介绍 (三)软件代码详解 Part.10(让PNG图片动起来)完结篇
  • MySQL学习/复习10视图/用户/权限/语言连接数据库
  • Vue实训---3-element plus的使用与布局
  • 深入解读:2023华为流程体系及落地实施
  • 【Bluedroid】A2DP SINK播放流程源码分析
  • BERT解析
  • 鸿蒙进阶-状态管理之@Prop@Link
  • 【老白学 Java】Warship v2.0(三)
  • 增量预训练(Pretrain)样本拼接篇
  • Gate学习(6) 指令学习3
  • WPF异步UI交互功能的实现方法
  • cangjie (仓颉) vscode环境搭建
  • .NET9 - 新功能体验(二)
  • 使用bcc/memleak定位C/C++应用的内存泄露问题
  • #Verilog HDL# 谈谈代码中如何跨层次引用
  • 下载安装Android Studio
  • #Verilog HDL# Verilog中的ifdef/ifndef/else等用法
  • 每日一练:位运算-消失的两个数字
  • CNN—LeNet:从0开始神经网络学习,实战MNIST和CIFAR10~
  • 第三十四篇 MobileNetV1、V2、V3模型解析