【JAVAEE】创建线程的方式及线程的常用方法

article/2025/9/17 0:41:32

目录

1.创建线程的四种方式

1.1继承Thread类

1.2实现Runnable接口

1.3匿名内部类

1.4lambda表达式

2.多线程的优势-增加运行速度

3.Thread类及常用方法

3.1构造方法

3.2常见属性

演示后台线程

演示线程是否存活

3.3线程中断

3.4线程等待-join()

3.5获取当前线程

3.6启动线程-start()

4.线程状态


1.创建线程的四种方式

Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。这里有四种方式可以实现Java创建线程:

1.继承Thread类并重写run()方法

2.实现Runnable接口并重写run()方法

3.通过匿名内部类的方式创建Thread和实现Runnable

4.通过lambda表达式来实现一个线程

1.1继承Thread类

Thread类是JDK中提供的表示线程的类。

重写run()方法,让线程执行指定的任务。

package lesson01;public class Demo01_Thread {public static void main(String[] args) {//创建自己定义的线程对象MyThread thread=new MyThread();//执行这个线程start方法是启动线程,并通知操作系统加入CPU调度thread.start();}
}
class MyThread extends Thread{//run方法中的代码,就表示线程要执行的任务@Overridepublic void run() {System.out.println("hello thread...");}
}

调用start()方法之后,JVM会调用系统API,并在系统中生成一个PCB来执行run()方法中的代码。

1.2实现Runnable接口

使用runnable接口定义任务的好处:

1.解耦(即 把不同的功能都给分开,如果要修改或查找相应的功能的时候可以直接指定的位置找),把定义线程,与定义任务分开。

2.把创建线程,与定义任务分开,以便修改代码时,可以统一修改。

package lesson01;public class Demo03_Runnable {public static void main(String[] args) {//创建Runnable对象MyRunnable runnable=new MyRunnable();//创建线程Thread thread=new Thread(runnable);//启动线程,参与CPU调度thread.start();}
}
//实现runnable接口
class MyRunnable implements Runnable{@Overridepublic void run() {while(true){System.out.println("生产皮包,金币+1...");try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}
}

1.3匿名内部类

通过匿名内部类的方式创建线程。

package lesson01;
//通过匿名内部类的方式创建线程
public class Demo05_Thread_Anon {public static void main(String[] args) {Thread thread=new Thread(){@Overridepublic void run() {while(true){System.out.println("hello thread");try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}};thread.start();}
}

通过匿名内部类的方式实现Runnable接口。

package lesson01;public class Demo06_Runnable_Anon {public static void main(String[] args) {Thread thread=new Thread(new Runnable() {@Overridepublic void run() {while(true){System.out.println("hello runnable");try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}}});thread.start();}
}

1.4lambda表达式

要使用lambda表达式实现接口,接口必须是一个函数式接口(即接口定义中,只有一个方法)。

格式:()->{要执行的代码块}

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

2.多线程的优势-增加运行速度

使用多线程编程主要是为了充分利用CPU资源,提升程序效率。

示例:分别对两个变量进行10亿次的自增。

1.串行:单线程

2.并行:多线程

定义次数:

private static long COUNT=10_0000_0000L;

串行操作,单线程:

private static void serial() {//记录开始时间long begin=System.currentTimeMillis();//第一个变量long a=0l;for(int i=0;i<COUNT;i++){a++;}long b=0l;for(int i=0;i<COUNT;i++){b++;}long end=System.currentTimeMillis();System.out.println("串行总耗时:"+(end-begin));}

并行操作,多线程:

private static void concurrency() throws InterruptedException{//记录开始时间long begin=System.currentTimeMillis();//创建第一个线程Thread t1=new Thread(()->{long a=0l;for(int i=0;i<COUNT;i++){a++;}});//第二个线程Thread t2=new Thread(()->{long b=0l;for(int i=0;i<COUNT;i++){b++;}});//启动线程t1.start();t2.start();//等待线程执行完成t1.join();t2.join();//结束时间long end=System.currentTimeMillis();System.out.println("并行总耗时:"+(end-begin));}

来看看结果吧:

 并行执行时间确实比串行执行时间短,可却不是串行的1/2,是因为每创建一个线程都是要消耗时间和资源的。

当把计算量改小一点:

private static long COUNT=10_000L;

结果就变成了:

所以并不是所有场景都适合使用多线程,是否使用需根据计算量来确定。

3.Thread类及常用方法

3.1构造方法

方法
说明
Thread()
创建线程对象
Thread(Runnable target)
使用 Runnable 对象创建线程对象
Thread(String name)
创建线程对象,并命名
Thread(Runnable target, String name)
使用 Runnable 对象创建线程对象,并命名
【了解】 Thread(ThreadGroup group,Runnable target)
线程可以被用来分组管理,分好的组即为线程组
Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

想要获取当前线程的名字,可以用下面这个方法:

Thread.currentThread().getName()

3.2常见属性

属性
获取方法
ID
getId()
名称
getName()
状态
getState()
优先级
getPriority()
是否后台线程
isDaemon()
是否存活
isAlive()
是否被中断
isInterrupted()
  • ID是线程的唯一标识,不同线程不会重复。
  • 名称是各种调试工具用的到
  • 状态表示线程当前所处的一个情况
  • 优先级高的线程理论上来说更容易被调度
  • 后台线程,JVM会在一个进程的所有非后台线程结束后,才会结束运行
  • 是否存活,简单理解,就是run()方法是否运行结束了

代码示例:创建一个名为”大圣“的线程,查看它的各种属性

package lesson02;public class Demo10 {public static void main(String[] args) {Thread thread=new Thread(()->{while(true){System.out.println("hello thread...");try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}},"大圣");thread.start();//打印thread对象中的属性System.out.println("线程ID="+thread.getId());System.out.println("线程名="+thread.getName());System.out.println("线程状态"+thread.getState());System.out.println("线程优先级"+thread.getPriority());System.out.println("线程是否后台"+thread.isDaemon());System.out.println("线程是否存活"+thread.isAlive());System.out.println("线程是否中断"+thread.isInterrupted());}
}

演示后台线程

创建线程时,默认是前台线程。

这里在线程启动前传入true设置线程为后台线程。

//在线程启动之前设置线程是否为后台thread.setDaemon(true);

代码示例:将线程设置为后台线程,main方法中是一个循环

package lesson02;public class Demo11_Daemon {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{while(true){System.out.println("hello thread...");//休眠一秒钟try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}});//在线程启动之前设置线程是否为后台thread.setDaemon(true);System.out.println("是否存活"+thread.isAlive());//启动线程thread.start();//休眠一会儿,确保PCB被创建成功Thread.sleep(500);System.out.println("是否存活"+thread.isAlive());System.out.println("main线程执行完成");System.out.println("是否存活"+thread.isAlive());}
}

 结果:

 程序退出了,因为main方法运行完了,后台线程影响不了程序是否退出,前台线程可以影响。

演示线程是否存活

演示线程启动前后的状态。

package lesson02;public class Demo12_Alive {public static void main(String[] args) {Thread thread=new Thread(()->{int count=0;while(true){System.out.println("hello thread...");try{Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//执行5次后退出线程count++;if(count==5){break;}}});System.out.println("线程启动前的状态:"+thread.isAlive());thread.start();System.out.println("线程启动后的状态:"+thread.isAlive());try{//等待子线程执行完成thread.join();}catch (InterruptedException e){e.printStackTrace();}System.out.println("线程执行完成的状态:"+thread.isAlive());System.out.println("主线程执行完成");}
}

看一看结果吧:

thread.isAlive()指的是系统的线程(PCB)是否存活,并不是我们new出来的Thread对象。

3.3线程中断

线程中断指的是停止或中断当前线程的任务

1.通过是否中断的标志位

    //定义一个中断标识private static boolean isQuit=false;

子线程处理任务3秒后,将标志位改为true,线程停止。

package lesson02;public class Demo13_Interrupted01 {//定义一个中断标识private static boolean isQuit=false;public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{while(!isQuit){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程执行结束");});//启动线程thread.start();//主线程休眠3秒,模拟子线程正在处理任务Thread.sleep(3000);//设置中断标志位为trueisQuit=true;//让子线程先结束Thread.sleep(1000);System.out.println("主线程执行结束");}
}

2.通过调用Thread类提供的Interrupted方法来中断

System.out.println("是否中断:"+Thread.currentThread().isInterrupted());

默认为false。

示例代码:
 

package lesson02;public class Demo14_Interrupted02 {public static void main(String[] args) throws InterruptedException {Thread thread=new Thread(()->{while(!Thread.currentThread().isInterrupted()){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();//异常处理中断线程//方式一:什么都不做//方式二:处理具体的逻辑//方式三:真正的中断break;}}System.out.println("是否中断:"+Thread.currentThread().isInterrupted());System.out.println("线程任务结束");});//启动线程thread.start();//主线程休眠3秒,模拟子线程正在处理任务Thread.sleep(3000);//中断线程,修改Thread中的中断标志thread.interrupt();//让子线程先结束Thread.sleep(1000);System.out.println("主线程执行结束");}
}

运行结果:

 sleep interrupted报错原因:

当线程在sleep或是阻塞状态的时候,调用interrupted方法,会中断当前的sleep休眠状态,并抛出异常。只有当线程在运行状态时,才会真正结束线程。

3.4线程等待-join()

join方法:明确等待线程的结束

方法
说明
public void join()
等待线程结束
public void join(long millis)
等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos)
同理,但可以更高精度

代码示例:

package lesson02;public class Demo15_Join {public static void main(String[] args) {Thread thread=new Thread(()->{for(int i=0;i<5;i++){System.out.println("hello thread"+i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("线程执行结束");});//启动线程thread.start();System.out.println("join之前,线程状态:"+thread.getState());System.out.println("join之前,是否存活:"+thread.isAlive());//使用join等待thread线程结束try{thread.join();}catch (InterruptedException e){e.printStackTrace();}System.out.println("join之后,线程状态:"+thread.getState());System.out.println("join之后,是否存活:"+thread.isAlive());System.out.println("主线程执行完成");}
}

运行结果:

3.5获取当前线程

方法
说明
public static Thread currentThread();
返回当前线程的引用
public class ThreadDemo {public static void main(String[] args) {Thread thread = Thread.currentThread();System.out.println(thread.getName());}
}

3.6启动线程-start()

run()方法和start()方法的区别:

run()方法:定义线程要执行的任务

start()方法:申请一个真正的系统线程(线程开始运行)

1.直接调用run()方法,并不会取申请一个真正的系统线程(PCB),只是单纯的调用对象的方法。

2.调用start()方法,JVM会调用本地方法取系统中真正的申请一个线程(PCB),并执行run()方法中的逻辑。

示例代码:

start()方法:

package lesson02;public class Demo16_StartRun {public static void main(String[] args) {Thread thread=new Thread(()->{while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});//启动线程thread.start();System.out.println("线程状态:"+thread.getState());System.out.println("主线程结束");}
}

结果:

run()方法:

package lesson02;public class Demo16_StartRun {public static void main(String[] args) {Thread thread=new Thread(()->{while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});//启动线程thread.run();System.out.println("线程状态:"+thread.getState());System.out.println("主线程结束");}
}

结果:

4.线程状态

线程状态指的是Thread对象的状态,不是PCB的状态。(Thread对象有自己的生命周期)

状态解释
NEW创建了一个Java线程,但还未调用start()方法
RUNNABLE运行或在就绪队列中
TERMINATED线程执行完成,PCB在操作系统中已销毁,但是Java对象还在
TIMED_WATING等待一段时间(有时间限制)
WAITING没有时间限制的等待
BLOCK等待锁的时候进入的阻塞状态

示例代码:

package lesson02;public class Demo17_State {public static void main(String[] args) throws InterruptedException {Thread t1=new Thread(()->{//第一种情况for(int i=0;i<1000_0000_00;i++){//啥也不干,等着让它结束}System.out.println("线程结束");});//启动之前打印一下线程状态//当前只是New出来了一个Thread类的对象System.out.println("启动之前的状态:"+t1.getState());//真正启动线程t1.start();System.out.println("启动之后的状态:"+t1.getState());//等待线程结束t1.join();System.out.println("PCB是否存活:"+t1.isAlive());System.out.println("线程执行完成后的状态:"+t1.getState());}
}

运行结果:

可以看到线程创建完成,但还没启动时状态为new,启动之后正在运行,状态为runnable,任务执行完成之后,PCB销毁,状态为terminated。

补充:

状态图


http://chatgpt.dhexx.cn/article/J4AGOubV.shtml

相关文章

创建线程的方式有那些?

目录 一.创建线程的4种方式 二.创建线程方式有什么区别&#xff1f; 一.创建线程的4种方式 &#xff08;1&#xff09;写一个类继承Thread&#xff0c;覆盖重写run方法 &#xff08;2&#xff09;创建一个Runnable类型的对象,实现run()方法,传入Thread的构造方法中 &#x…

创建线程几种方式

创建线程的几种方式&#xff1a; 方式1&#xff1a;通过继承Thread类创建线程 步骤&#xff1a;1.定义Thread类的子类&#xff0c;并重写该类的run方法&#xff0c;该方法的方法体就是线程需要执行的任务&#xff0c;因此run()方法也被称为线程执行体 2.创建Thread子类的实例&a…

线程创建的四种方式

java中创建线程的四种方法以及区别 Java使用Thread类代表线程&#xff0c;所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程&#xff0c;如下所示&#xff1a; 1&#xff09;继承Thread类创建线程 2&#xff09;实现Runnable接口创建线程 3&am…

四种线程创建方式

一. 继承Thread类 继承Thread类创建线程的步骤: 创建一个自定义类继承Thread类,重写run()方法,将所要单独线程运行写入run()方法中;创建Thread类的子类的对象;调用该对象的start()方法,该start()方法表示开启线程,然后调用执行run方法; Testpublic void test() {Thread.curre…

创建线程的四种方式

我们创建线程池一般有四种方式&#xff0c;分别是&#xff1a; 1.继承Thread类&#xff0c;重写run()方法&#xff1b; 2.实现Runnable接口&#xff0c;重写run()方法&#xff1b; 3.实现Callable接口&#xff0c;重写call()方法&#xff1b; 4.使用线程池创建线程&#xff1b;…

线程创建常用的四种方式

java中创建线程的四种方法以及区别 Java使用Thread类代表线程&#xff0c;所有的线程对象都必须是Thread类或其子类的实例。Java可以用四种方式来创建线程&#xff0c;如下所示&#xff1a; 1&#xff09;继承Thread类创建线程 2&#xff09;实现Runnable接口创建线程 3&…

银行测试核心项目之测试阶段分享

最近有小伙伴说「想了解核心系统建设中&#xff0c;冒烟、SIT、UAT、回归测试的重点&#xff0c;如何设计测试案例&#xff0c;或相关的资料推荐等」。 这个话题很笼统&#xff0c;测试这一块儿除了业务测试&#xff0c;还有性能测试、安全测试等&#xff1b;以及不同的角色对…

金融银行测试面试题分享

1、网上银行转账是怎么测的&#xff0c;设计一下测试用例。 回答思路&#xff1a; 宏观上可以从质量模型&#xff08;万能公式&#xff09;来考虑&#xff0c;重点需要测试转账的功能、性能与安全性。设计测试用例可以使用场景法为主&#xff0c;先列出转账的基本流和备选流。…

2022年软件测试——精选金融银行面试真题

前言 小伙伴们好久不见呀&#xff0c;现已经到了八月份了过了这一个月就是金九银十了&#xff0c;在这里呢笔者给大家准备了一份软件测试金融方面的面试题&#xff0c;笔者在这里就不多说废话了哟&#xff0c;咱们直接进入正题哈。 1、P2P你们也测试后台管理吗&#xff1f;个人…

金融行业软件测试

金融行业软件测试 一、什么是金融行业二、金融行业的业务特点1. 金融行业的业务特点 三、金融行业测试主要测试范围1. 功能测试2. 业务验证测试3. 客户端测试4. 接口测试5. 性能测试6. 安全性测试 四、金融行业软件测试的现状五、第三方测试的优点 一、什么是金融行业 金融业是…

走出新手村,软件测试银行项目怎么测试 + 面试题(答案)

前言 业务&#xff1a; 银行类app具体模块业务讲解&#xff1a; 掌上生活&#xff08;消费/理财&#xff09; 消费&#xff1a; 与电商平台业务类似 饭票&#xff1a;GPS定位城市服务、饭票购买消费、餐厅查询、代金券、周三五折、banner图、我的饭票、我的抵扣券 影票 …

【工作总结】银行软件测试工作总结

最近换工作进入到外包公司&#xff0c;驻点到银行进行集成测试工作&#xff0c;为了让自己更熟悉金融行业&#xff0c;特别是银行业相关业务&#xff0c;以及总结自己测试的一些经验&#xff0c;希望将自己了解和学习的内容记录下来。主要从以下几个方面学习&#xff1a; 一、…

大咖or学员?金融银行软件测试案例分享!

2019年4月14日汇智动力学院在成都校区开展了本年度的第一次线下技术交流沙龙&#xff08;银行金融测试方向&#xff09;&#xff1b; 刘德宝老师做技术分享 通过在上个月末举办的老学员周末娱乐活动&#xff08;雀圣大赛&#xff09;&#xff0c;我们做了一系列的问卷调查&…

银行软件测试面试问题

测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行&#xff0c;即是通常说的软件的可移植性。 兼容的类型&#xff0c;如果细分的话&#x…

浦发银行软件测试面试真题(小编面试亲测)

对于想要面试去银行面试的小伙伴们看过来&#xff0c;今天为大家总结了浦发银行的面试题&#xff0c;其实很多面试题很多公司都差不多。主要看自己如何灵活回答。以下的问题小编盆友之前面试非浦发银行的银行项目也有被问到过&#xff0c;是在一面的时候被问到的。答案仅作为参…

金融银行软件测试超大型攻略,最受欢迎的金融银行大揭 秘附面试题

零、为什么做金融类软件测试 举个栗子&#xff0c;银行里的软件测试工程师。横向跟互联网公司里的测试来说&#xff0c;薪资相对稳定&#xff0c;加班少甚至基本没有&#xff0c;业务稳定。实在是测试类岗位中的香饽饽&#xff01; 一、什么是金融行业 金融业是指经营金融商…

银行软件测试简历模板,找工作的小伙伴看过来了

目录 目录 个人简历 教育背景 工作经历 自我评价 专业技能 ​编辑 个人简历 姓  名&#xff1a; 性  别&#xff1a; 学  历&#xff1a; 经  验&#xff1a; 手  机&#xff1a; 邮  箱&#xff1a; 政治面貌&#xff1a; 意向岗位&#xff1a; 软…

7个银行的软件测试项目实战,别再说简历项目不知道怎么写了

目录 前言 项目描述1&#xff1a;上海华瑞银行直连票据项目 项目描述2&#xff1a;平安金服风控中台系统 项目描述3&#xff1a;众安创展APP项目 项 目4&#xff1a; 招商银行VTM自助渠道服务系统 项 目5&#xff1a;招商银行票据支付 项 目6&#xff1a; 平安银行风控系…

银行测试——软件测试永远的神

为什么要做金融类软件测试 举个例子&#xff0c;比如银行的软件测试工程师&#xff0c;横向和互联网公司的测试人员比较来说&#xff0c;工资比较稳定&#xff0c;加班很少甚至没有&#xff0c;业务稳定。 实在是测试类岗位中的香饽饽&#xff01;【点击文末小卡片免费领取软件…

软件测试之银行项目重点测试点

在我们的日常在金融或银行软件测试工作中都有哪些内容需要测试&#xff1f;在这些测试的内容中如何去更好的掌握测试技能保证测试质量&#xff0c;一起来学习探讨交流。 下面为银行测试点的概括&#xff1a; 根据上图&#xff0c;我们可以从以下几个方面重点关注&#xff1a; …