【JavaEE】线程的创建及常见方法解析(Tread类)

这篇具有很好参考价值的文章主要介绍了【JavaEE】线程的创建及常见方法解析(Tread类)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.Tread类介绍

2线程的构造方法——创建线程

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

2.使用Runnbable接口创建线程

3.继承 Thread, 重写 run, 使用匿名内部类

4.实现 Runnable, 重写 run, 使用匿名内部类

5.使用 lambda 表达式(重点掌握)

3.Tread类常见方法解读 

3.1Tread类常见构造方法 

3.2 Tread类的几个常见属性

3.3启动一个线程-start()方法

3.4中断一个线程

3.5等待一个线程-join() 

3.6休眠线程

3.7 实现一个简单的多线程

4.线程的状态

4.1线程的六种状态 

4.2线程状态和状态转移


1.Tread类介绍

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联,每个执行流(线程),也需要有一个对象来描述, Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度、线程管理。

2线程的构造方法——创建线程

无论使用哪一个方法创建线程,我们都需要将其中的run方法重写(run方法中写入的是线程需要执行的任务),它的作用就相当于主线程的main方法。

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

这个构造方法没有参数,通过创造一个类继承Thread类来实现线程 ,线程必须重写run()方法才算完成。当我们new一个线程时,此时的线程还没开始执行,再用创建的类调用start()方法才算运行了这个线程。

class TestTread extends Thread{
    @Override
    public void run() {
        System.out.println("this tread1");
    }
}
public class testDemo2 {
    public static void main(String[] args) {
        Thread thread=new TestTread();
        thread.start();
    }
    
}

2.使用Runnbable接口创建线程

我们可以看出,该构造方法的参数类型是一个接口类,因此我们需要创建一个类来实现这个接口,再new一个实现Runnable的类对象,再new一个线程,将之前创建的对象放入到参数这里。

class TestTread2 implements Runnable {
    @Override
    public void run() {
        System.out.println("this t2");
    }
}
public class testDemo2 {
    public static void main(String[] args) {
        //new一个实现Runnable接口的对象
        TestTread2 testTread2=new TestTread2();
        //传入参数完成线程的创建
        Thread t2=new Thread(testTread2);
        t2.start();
    }

}

3.继承 Thread, 重写 run, 使用匿名内部类

 使用匿名内部类可以省略创建对象的过程,可以减少资源消耗。

public class testDemo3 {
    public static void main(String[] args) {
        //通过Thread匿名内部类的方法创建一个线程
        Thread t1=new Thread() {
            @Override
            public void run() {
                System.out.println("this t1");
            }
        };
        t1.start();
    }

}

4.实现 Runnable, 重写 run, 使用匿名内部类

这个和3一样,可以少创建一个对象,减少资源的消耗。 

public class testDemo4 {
    public static void main(String[] args) {
        Thread t1=new Thread(new  Runnable() {
            @Override
            public void run() {
                System.out.println("this t1");
            }
        });
        t1.start();
    }
}

5.使用 lambda 表达式(重点掌握)

它的实现原理和匿名内部类相似,这点不了解lambda表达式的,可以去看一下如何使用。

public class testDemo4 {
    public static void main(String[] args) 
        Thread t2=new Thread(()->{
            System.out.println("this t2");
        });
        t2.start();
    }
}

3.Tread类常见方法解读 

3.1Tread类常见构造方法 

方法 说明
Thread() 创建线程对象
Thread(Runnable target) 使用 Runnable 对象创建线程对象
Thread(String name) 创建线程对象,并命名
Thread(Runnable target, String name) 使用 Runnable 对象创建线程对象,并命名
【了解】Thread(ThreadGroup group,
Runnable target)
线程可以被用来分组管理,分好的组即为线程组,这
个目前我们了解即可

3.2 Tread类的几个常见属性

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

3.3启动一个线程-start()方法

调用 start 方法, 才算是在操作系统的底层创建出一个线程. 

public class testDemo4 {
    public static void main(String[] args) {
        Thread t1=new Thread(new  Runnable() {
            @Override
            public void run() {
                System.out.println("this t1");
            }
        });
        t1.start();
    }
}

3.4中断一个线程

方法 说明
public void interrupt() 中断对象关联的线程,如果线程正在阻塞,则以异常方式通知,
否则设置标志位
public static boolean
interrupted()
判断当前线程的中断标志位是否设置,调用后清除标志位
public boolean
isInterrupted()
判断对象关联的线程的标志位是否设置,调用后不清除标志位
  • 使用 thread 对象的 interrupted() 方法通知线程结束 
public class testDemo6 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(() ->{
            while (!Thread.interrupted()) {
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    break;
                }
            }
        });
        t1.start();
        Thread.sleep(1000*2);
        t1.interrupt();
    }
}

t1收到通知的方式有两种:

1.如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志.

  • 当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程(加break).

 2.否则,只是内部的一个中断标志被设置,thread 可以通过

  • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
  • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志
  • 使用 Thread.isInterrupted() , 线程中断会清除标志位

标志位是否清除, 就类似于一个开关.
Thread.Interrupted() 相当于按下开关, 开关自动弹起来了. 这个称为 "清除标志位".

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    // //打印标准位
                    System.out.println(Thread.interrupted());
                }
        });
        thread.start();
        thread.interrupt();
    }
}

结果:【JavaEE】线程的创建及常见方法解析(Tread类)

观察结果可以看出,已知interrupted()初始是true,之后就打印的值就是false,因为标志位已经被删除了。

  • 使用 Thread.currentThread().isInterrupted() , 线程中断标记位不会清除

 标志位是否清除, 就类似于一个开关.
Thread.currentThread().isInterrupted() 相当于按下开关之后, 开关弹不起来, 这个称为"不清除标志位".

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    // //打印标准位
                    System.out.println(Thread.currentThread().isInterrupted());
                }
        });
        thread.start();
        thread.interrupt();
    }
}

结果: 【JavaEE】线程的创建及常见方法解析(Tread类)

观察结果可以清晰的看出,打印的全是true,这是因为标志位没有被删除,它的值还是true。

3.5等待一个线程-join() 

方法 说明
public void join() 等待线程结束
public void join(long millis) 等待线程结束,最多等 millis 毫秒
public void join(long millis, int nanos) 同理,但可以更高精度
public class testDemo7 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1=new Thread(()->{
            for (int i = 0; i < 10; i++) {
                System.out.println("第"+i+"次打印"+Thread.currentThread().getName());
            }
            System.out.println("----------");
        });
        Thread t2=new Thread(()->{
            for (int i = 0; i < 10; i++) {
                System.out.println("第"+i+"次打印"+Thread.currentThread().getName());
            }
        });
        t1.start();
        //t2等待t1执行完毕,t2才可执行
        t1.join();
        t2.start();
    }
}

 结果:【JavaEE】线程的创建及常见方法解析(Tread类)

 可以看出使用了join(),两个线程不再是杂乱运行了,而是先运行完t1线程,再运行的t2线程。这就是join 的作用。

3.6休眠线程

这个是比较熟悉一组方法,有一点要记得,因为线程的调度是不可控的,所以,这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间的。

方法 说明
public static void sleep(long millis) throws InterruptedException 休眠当前线程 millis
毫秒
public static void sleep(long millis, int nanos) throws
InterruptedException
可以更高精度的休眠

3.7 实现一个简单的多线程

 这两个线程任务都是打印自己的名字,其中使用的currentThread()方法是或者当前线程的引用,getName()方法就是或者线程的名字(就算我们没有给线程起名字,系统也会给它自定义一个名字)。

public class testDemo5 {
    public static void main(String[] args) {
        Thread t1=new Thread(()->{
            while (true) {
                //打印线程名称
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2=new Thread(()->{
            while (true){
                //打印线程名称
                System.out.println(Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        //执行线程任务
        t1.start();
        t2.start();
    }
}

代码实现结果:【JavaEE】线程的创建及常见方法解析(Tread类)

观察可以看出,两个线程是交叉运行,并且是杂乱运行,好不规律可言。没错,线程的并发就是没有规律的,谁先运行取决于操作系统如何调度线程,因此线程是"抢占式执行"。

4.线程的状态

4.1线程的六种状态 

  • NEW: 安排了工作, 还未开始行动,刚刚创建一个Tread对象,还没开始工作。
  • RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作(正在CPU上执行任务或者在就绪队列中随时可以在CPU上执行的)。
  • BLOCKED: 这几个都表示排队等着其他事情(synchronized加锁)。
  • WAITING: 这几个都表示排队等着其他事情。
  • TIMED_WAITING: 这几个都表示排队等着其他事情(使用sleep或者join方法引起的)。
  • TERMINATED: 工作完成了。

4.2线程状态和状态转移

【JavaEE】线程的创建及常见方法解析(Tread类)  举个例子,看下图:

【JavaEE】线程的创建及常见方法解析(Tread类)文章来源地址https://www.toymoban.com/news/detail-401098.html

到了这里,关于【JavaEE】线程的创建及常见方法解析(Tread类)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaEE 初阶篇-深入了解进程与线程(常见的面试题:进程与线程的区别)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录         1.0 进程概述         2.0 线程概述         2.1 多线程概述         3.0 常见的面试题:谈谈进程与线程的区别         4.0 Java 实现多线程的常见方法         4.1 实现多线程方法 - 继承

    2024年04月13日
    浏览(48)
  • javaEE初阶——多线程(九)——JUC常见的类以及线程安全的集合类

    T04BF 👋专栏: 算法|JAVA|MySQL|C语言 🫵 小比特 大梦想 此篇文章与大家分享多线程专题的最后一篇文章:关于JUC常见的类以及线程安全的集合类 如果有不足的或者错误的请您指出! 3.1Callable接口 Callable和Runnable一样,都是用来描述一个任务的 但是区别在于 ,用Callable描述的任务是有

    2024年04月25日
    浏览(43)
  • 【JavaEE初阶】多线程进阶(五)常见锁策略 CAS synchronized优化原理

    乐观锁:预测锁竞争不是很激烈。 悲观锁:预测锁竞争会很激烈。 以上定义并不是绝对的,具体看预测锁竞争激烈程度的结论。 轻量级锁加锁解锁开销比较小,效率更高。 重量级锁加锁解锁开销比较大,效率更低。 多数情况下,乐观锁也是一个轻量级锁。 多数情况下,悲

    2024年02月03日
    浏览(46)
  • 【JavaEE】JUC(java.util.concurrent)的常见类以及线程安全的集合类

    目录 1、JUC(java.util.concurrent)的常见类 1.1、Callable接口的用法(创建线程的一种写法)  1.2、ReentrantLock可重入互斥锁 1.2.1、ReentrantLock和synchronized的区别  1.2.2、如何选择使用哪个锁 1.3、Semaphore信号量 1.4、CountDownLatch  2、线程安全的集合类 2.1、多线程环境使用ArrayList  2.2、

    2024年02月07日
    浏览(49)
  • 【JavaEE】_多线程Thread类及其常用方法

    目录 1. Thread类常用构造方法 2. Thread类的几个常见属性 3. 启动一个线程 4. 中断一个线程 4.1 方法1:手动设置标志位 4.2 方法2:使用Thread内置的标志位 5. 等待一个线程 6. 获取当前线程引用 7. 休眠当前线程 方法 说明 Thread() 创建线程对象 Thread(Runnable target) 使用Runnable对象创建

    2024年02月20日
    浏览(39)
  • 【多线程初阶】Thread类常见方法以及线程的状态

    本文是属于多线程初阶内容系列的, 如果还没有学习过之前文章的, 请先移步博主的之前的文章进行学习, 本文就是在学会线程的创建后, 再带大家认识一下 Thread 类以及其常见的方法, 再给大家讲解一下线程都有哪些状态. 关注收藏, 开始学习吧🧐 通过我们上篇文章的学习, 我

    2024年02月16日
    浏览(38)
  • 单线程、同步、异步、预解析、作用域、隐式全局变量、对象创建、new

    cpu 资源分配的最小单位 一个进程可以有多个线程 cpu 调度的最小单位 线程建立在进程的建立基础上的一次程序的运行单位 线程分为:单线程 多线程 单线程:js是单线程 (同一个时间只能完成一个任务) 多线程:百度是多线程 同步任务是指在主线程上排队的任务,只有当前

    2024年01月22日
    浏览(48)
  • QT创建线程的方法:一步步教你创建和启动线程

    目录 线程概念及官方文档  一、线程的创建:继承方式 二、线程的创建:QObject 对象(moveToThread) 2.1 创建任务类 2.2 添加线程启动(定时器启动) 2.3 添加线程启动(start信号启动) 三、线程类的基本接口和使用 3.1启动 和终止线程 3.2 线程延迟 3.3 线程同步及通信方式 3.4

    2024年02月13日
    浏览(44)
  • Java 创建线程的方法

    🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开兴好久好久😎 📚系列专栏:Java全栈,计算机系列(火速更新中) 💭 格言:种一棵树最好的时间是十年前,其次是现在 🏡动动小手,点个关注不迷路,感

    2024年02月07日
    浏览(41)
  • 【Java系列】详解多线程(二)——Thread类及常见方法(上篇)

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得,欢迎大家在评论区交流讨论💌 我们先来回顾一下线程与进程之间的联系。 我们知道多进程

    2024年02月04日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包