Thread的基本操作
创始人
2025-05-30 06:30:33
0

目录

一 .  创建线程

    1) 继承Thread类 

   2) 使用Runnable 来创建线程

 3) 继承Thread , 使用匿名内部类

 4)  实现Runnable , 使用匿名内部类

5)  lambda 表达式 创建线程(常用)

二 . Thread 构造方法 与 常用方法

1. 无参构造 Thread()

2. 只有Runnable 参数 Thread(Runnable)

 3. 带有Runnable 与 String  的构造方法 Thread(Runnable,String)

4. 只带有String 参数的构造方法 Thread(String)

 ​Thread 常见属性

1) 获得当前线程的引用

2) 获取ID

3) 获取名称

4) 获取优先级

5) 获取线程的状态

6) 是否存活

7)  是否被中断

 8) 是否后台线程

关于线程中的 run() 方法

三 . 线程的状态

1) 线程休眠

2) 线程中断

3) 线程等待

总结 : 


一 .  创建线程

    1) 继承Thread类 

class MyThread extends Thread {@Overridepublic void run() {System.out.println("通过继承来创建线程");}
}
public class Demo1 {public static void main(String[] args) {Thread t = new MyThread();t.start();}
}

   2) 使用Runnable 来创建线程

这种写法通过实现Runnable , 来描述线程中要执行的任务

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("使用实现Runnable 接口 创建线程");}
}
public class Demo2 {public static void main(String[] args) {Thread t = new Thread(new MyRunnable());t.start();}
}

 3) 继承Thread , 使用匿名内部类

public class Demo3 {public static void main(String[] args) {Thread t = new Thread() {@Overridepublic void run() {System.out.println("继承Thread,匿名内部类");}};t.start();}
}

 4)  实现Runnable , 使用匿名内部类

实现方法跟上面相同.(实现了Runnable,重写了run()方法)

public class Demo4 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("实现Runnable 接口,匿名内部类");}});t.start();}
}

5)  lambda 表达式 创建线程(常用)

public class Demo5 {public static void main(String[] args) {Thread t = new Thread(() -> {System.out.println("lambda表达式");});}
}

总结 : 通常认为Runnable 这种写法更好一点 ~~ 能够做到让线程和线程执行的任务, 更好的进行解耦.  (写代码希望 : 高内聚, 底耦合)

Runnable 单纯的只是描述了一个任务 ~ 至于这个任务是要通过一个进程来执行,还是线程执行,或者是线程池来执行,还是协程来执行, Runnable本身别不关心,Runnable里面的代码也不关心.

 

二 . Thread 构造方法 与 常用方法

在这里主要将一下几个构造方法 : 

1. 无参构造 Thread()

 

2. 只有Runnable 参数 Thread(Runnable)

 3. 带有Runnable 与 String  的构造方法 Thread(Runnable,String)

4. 只带有String 参数的构造方法 Thread(String)

 ​Thread 常见属性

Thread 的几个常见属性

1) 获得当前线程的引用

Thread.currentThread();

2) 获取ID

3) 获取名称

4) 获取优先级

public static void main(String[] args) {Thread t = new Thread(() -> {//获取当前线程的IDSystem.out.println(Thread.currentThread().getId());//获取当前线程的名称System.out.println(Thread.currentThread().getName());//获取当前线程的优先级System.out.println(Thread.currentThread().getPriority());System.out.println("hello");});t.start();}

5) 获取线程的状态

这里的状态会分为很多种,在后面会重点介绍.

6) 是否存活

这里的线程存活指的是系统内核里的那个线程,是否存活的

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {//空}});System.out.println(t.isAlive());t.start();System.out.println(t.isAlive());}

7)  是否被中断

这是线程中的一个标志位 默认值为false.

public class Demo11 {public static void main(String[] args) {Thread t = new Thread(() -> {System.out.println("hello");});t.start();System.out.println(t.isInterrupted());}
}

 我们通过interrupt() 方法就可以将这个标志位由false 变为 true;

public static void main(String[] args) {Thread t = new Thread(() -> {System.out.println("hello");});t.start();System.out.println(t.isInterrupted());t.interrupt();System.out.println(t.isInterrupted());}

 8) 是否后台线程

什么是前台线程 ??  什么是后台线程??

后台线程不阻止java进程结束.

即使后线程还没执行完, java进程该结束就结束了~~

前台线程更好相反

前台线程会阻止java线程结束, 必须得java进程中所有的前台线程都执行完 java进程才结束.

通过Thread 创建出来的线程都是前台线程,

可以通过setDaemon() 将前台设置为后台

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {//空}});t.start();System.out.println(t.isDaemon());}

调用setDaemon()

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {//空}});System.out.println(t.isDaemon());//注意这里在设置前后台线程时//这个语句要放在t.start()之前t.setDaemon(true);t.start();System.out.println("结束");}

关于线程中的 run() 方法

如果通过 t.run() 去调用 ,  那么它会是一个普通的方法去执行, 存在main线程中

public static void main(String[] args) {Thread t = new Thread(() -> {int j = 5;while (j-- > 0) {System.out.println("t:" + j);}});t.run();int i = 10;while (i-- > 0) {System.out.println("main :" + i);}}

 

通过上述的运行结果我们可以看出,先执行完run()方法,然后再向后执行

如果将t.run() 转换为 t.start()

run() 方法补充 : 

 多线程如何执行 (补充): 

 

三 . 线程的状态

1) 线程休眠

Thread.sleep()  : 让当前线程进入休眠 , 括号里面放入休眠的时间

Thread.sleep(1000) : 让当前线程休眠1秒  

public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();System.out.println("------");}

hello在打印的时候也是 1秒打印一个

 

2) 线程中断

两种方式 : 1. 自己设立一个标志 来控制线程的运行

                  2. 使用线程中的isInterrupted()

1. 手动设置一个标志位 , 来控制线程是否要结束执行~~

t 线程 与 main 线程  都是在一个进程内, 因此它们用了同一份虚拟地址空间.

因此 , 在main线程中修改的isQuit 就会该变 t 线程中的isQuit.

public class Demo15 {public static boolean isQuit = false;public static void main(String[] args) {Thread t = new Thread(() -> {while (!isQuit) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}isQuit = true;System.out.println("中断t线程");}
}

2. 使用isInterrupted() 来修改线程的标志位

public class Demo16 {public static void main(String[] args) {Thread t = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}t.interrupt();System.out.println("-----");}
}

通过上述的输出结果 : 代码报错之后 , 没有中断 t 线程,还是在继续的执行程序

问题如下 :

修改后的代码 : 

public class Demo16 {public static void main(String[] args) {Thread t = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();break;}}});t.start();try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}t.interrupt();System.out.println("-----");}
}

 

这样当它打印完异常日志后 , 我们直接让它break 退出循环.

3) 线程等待

实现一个代码通过 t 线程让i 自增10次

public class Demo17 {private static int i = 0;public static void main(String[] args) {Thread t = new Thread(() -> {for (int j = 0; j < 10; j++) {i++;}});t.start();System.out.println(i);System.out.println("main线程结束");}
}

 输出结果为 0 

问题如下 : 

 修改代码 : 

public class Demo17 {private static int i = 0;public static void main(String[] args) {Thread t = new Thread(() -> {for (int j = 0; j < 10; j++) {i++;}});t.start();try {t.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(i);System.out.println("main线程结束");}
}

对于线程等待的补充 : 

上述 t.join()  这句代码是在main线程中, 因此就是让main线程等待 t 线程执行完成.

要注意这里的等待与被等待对象.

另外我们还可以设置等待的时间

t.join(2000) : 表示main线程只等待 t 线程2秒钟. 然后就继续去执行main方法其余语句.

总结 : 

综上的线程的状态, 我们可以构造一个图

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...