JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!)

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

一、创建线程

Java中创建线程的写法有很多种!!!这里介绍其中5种。

方法1:继承Thread类,重写run

创建一个类,让这个类继承自Thread父类,再重写我们的run方法就可以了。
使用Thread类,不需要import别的包,因为它是再Java.lang下面的。

//写一个类,继承自标准库的Thread
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("hello word!");
    }
}
public class ThreadDemo1 {
    public static void main(String[] args) {
        //创建线程,是希望线程成为一个独立的执行流(执行一段代码)
        //创建线程是相当于雇了个人帮我们干活
        Thread t = new MyThread(); //这里就不用new标准库的thread的了,而是刚才创建的子类
        t.start(); //线程中的特殊方法,启动一个线程
    }
}

注意:
start() 是创建了一个新的线程,由新的线程来执行t.run()方法。

这个新的线程就是调用操作系统的API
通过操作系统内核创建新线程的PCB,并且把要执行的指令交给这个PCB,当PCB被调度到了CPU上执行的时候,也就执行到了线程run方法的代码了。

如果只是在main方法中输出"hello world",你的Java进程主要就是有一个线程(调用main方法的线程),主线程通过t.start(),主线程调用stat(),创建出一个新的线程,新的线程调用t.run(),如果我们run()方法执行完毕,这个线程自然销毁了。

方法2:实现Runnable接口

//Runnable 作用是描述一个“要执行的任务”,run 方法就是任务的执行细节。
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class ThreadDemo2 {
    public static void main(String[] args) {
        //这只是描述了个任务
        Runnable runnable = new MyRunnable();
        //把任务交给线程来执行
        Thread t = new Thread(runnable);
        t.start();

    }
}

解耦合。目的就是为了让 线程和任务(线程要干的活)之间分离开。
未来如果要改代码不用多线程,使用多进程、线程池或协程……此时代码改动比较小

方法3:使用匿名内部类,继承Thread

//使用匿名内部类来创建线程
public class ThreadDemo3 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                super.run();
                System.out.println("hello");
            }
        };
        t.start();
    }
}

其中new Thread()
①创建了一个Thread子类,(子类没有名字)所以才叫做“匿名”;
②创建了子类的实例,并且让 t 引用指向该实例。

方法4:使用匿名内部类,实现Runable

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

这个写法和方法2本质相同,只不过把实现Runable任务交给匿名内部类的语法。
此处是创建了一个类,实现Runable,同时创建了类的实例,并且传给Thread的构造方法。

方法5:使用Lambda表达式

此方法是最简单,最推荐的方法。

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

把任务用lambda表达式来描述,直接把lambda传给Thread构造方法。
lambda就是个匿名函数(没有名字的函数),用一次就没有了。
() - > {}

二、Thread类及常见方法

Thread类是JVM用来管理线程的一个类,换句话说,每个线程都有一个Thread对象与之相关联
可以说,每个执行流,都需要有一个对象来描述,类似下图,而Thread类的对象,就是用来描述一个线程执行流的,JVM会将这些Thread对象组织起来,用于线程调度,线程管理。
JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea

1. Thread的常见构造方法

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
其中:
最后两个Thread(String name)Thread(Runnable target, String name) 多了个name参数,这个参数是为了方便调试而给线程起了个名字。
线程的默认的名字为 thread-0,1,2之类的。

构造方法的格式如下:

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread(“这是我的名字”);
Thread t4 = new Thread(new MyRunnable(), “这是我的名字”);

例如:

public class ThreadDemo6 {
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello");
                }
            }
        },"mythread");
        t.start();
    }
}

2. Thread的几个常见属性

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea

  • ID是线程的唯一标识,不同线程不会重复;

  • 名称是各调试工具用到的;

  • getStat:构造方法里起的名字;

  • getStat:线程状态,Java中线程的状态要比操作系统原生的状态更丰富一些;

  • getPrior:线程的优先级可以获取,也可以设置,但是设置了不管用,因为优先级是很多要素影响得到的;

  • isDaem:是否守护线程,是否“后台线程”
    前台线程会阻止进程结束,前台线程的工作没做完,进程是完不了的;
    后台线程,不会阻止线程结束,后台线程没做完,进程是可以结束的。
    代码里手动创建的线程,默认都是前台线程,包括main,默认也是前台;
    其他JVM自带的线程都是后台线程。
    也可以手动使用setDaemon设置成后台线程,是后台线程,就是守护线程。
    JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
    把t设置成 守护/后台线程,此时进程的结束与否就和t无关了。

  • isAlive()是否存活:判断当前系统中的这个线程是不是有了。
    在用户态(应用程序)中创建了一个线程Thread t = new Thread();
    程序中通过t.start();来调用,
    在真正调用start之前,调用t.isAlive(),此时是false,此时内核态(操作系统内核)里没有这个线程;
    而调用start后,就会让内核创建一个PCB,此时这个PCB才表示一个真正的线程,此时isAlive是 true。
    也可以简单的理解为start/run方法是否允许结束了。

    另外,如果内核里线程把run执行完了,此时线程销毁,PCB随之释放。但是Thread t 这个对象还不一定被释放,此时isAlive也是false。
    【总结】
    如果 t.run还没执行,isAlive 为 false
    如果 t,run 正在执行,isAlive 为 true
    如果 t.run执行结束,isAlive 为 false

    通过上述我们可以了解,Thread t这个对象比内核里的PCB存在的周期要久。

3. 启动一个线程——start()

之前我们已经看到了如何通过复写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

  1. 复写run方法是提供给线程要做的事情的指令清单;
  2. 线程对象可以认为是把李四、王五等新线程叫过来了;
  3. 而调用start()方法,就是相当于喊一声“行动起来!”,线程才真正独立去执行了。

总之,run方法是描述了我们要做啥任务,而stat才是真正开始任务。
调用start方法,才真正在操作系统的底层创建出一个线程!

4. 终止一个线程

终止线程的意思是,不是让线程立即就停止,而是通知线程,你应该要停止了,但是是否真的停止,取决于线程这里的具体写法。终止线程有以下两种方式:

  1. 使用标志位来控制线程是否要停止;
public class ThreadDemo8 {
    private static boolean flag = true;

    public static void main(String[] args) throws InterruptedException{
        Thread t = new Thread(() -> {
            while (flag) { //当flag为true的时候
                System.out.println("hello!!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
            t.start();

            Thread.sleep(3000); //当执行到第三秒的时候,把flag变为false,结束循环
            flag = false;
        }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
这个代码之所以能够起到作用,修改flag,t线程就结束,完全取决于t线程内部的代码,代码里通过flag控制循环。
因此,这里只是告诉让这个线程结束,这个线程是否要结束,什么时候结束,都是线程内部自己代码来决定的。因为是while(flag)所以3秒钟后结束了,要是while(true),怎么改都不会结束循环。

此方法的缺点:自定义变量这种方式,不能及时相应,尤其在sleep休眠的时间比较久的时候。

  1. 使用Thread自带的标志位( interrupt() 方法),来进行判定是否要停止。

这里调用interrupt,只是通知终止,不是线程一定要乖乖终止!!
【格式】

while (!Thread.currentThread().isInterrupted()) {}

其中:
① while判定,判断条件是true,则执行方法体内的循环,为false,则循环结束;
Thread.currentThread() :这是Thread类的静态方法,通过这个方法可以获取到当前线程。哪个线程调用这个方法,就是得到哪个线程的对象引用(类似于this);
isInterrupted() 为true表示被终止,为false表示未被终止,继续执行;
④ 前面有个 ! 逻辑取反符,所以当isInterrupted() 为true时,!isInterrupted() 就为false,反之,则为true。

interrupt 会做两件事:
① 把线程内部的标志位(boolean)给设置成 true;
② 如果线程在进行sleep,就会触发异常,把sleep给唤醒。

但是sleep在唤醒的时候,还会做一件事,就是把刚在设置的这个标志位,再设置回false。(清空了标志位),这就导致,当sleep的异常被catch完了之后,循环继续执行!
如下述例子:

【例1】:线程t忽视了终止请求

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

        t.interrupt(); //3秒后,把线程内部的标志位(boolean)给设置成 true
    }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
此时循环会一直执行下去!这里就是sleep清空的例子。

【例2】:线程t立即响应了终止请求(加了break)

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

        t.interrupt(); //3秒后,把线程内部的标志位(boolean)给设置成 true
    }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea

【例3】:稍后进行终止
执行完等了3秒钟,代码执行完毕。

public class ThreadDemo9 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println("hello thread!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    //稍后再终止!
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                }
                    break;
                }
            }
        });
        t.start();
        Thread.sleep(3000);

        t.interrupt();
    }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea

【总结】
大前提:调用interrupt,只是告诉线程你该终止了,但是它是不是真的终止,这是它自己的事情。
注意其中sleep有个清楚标志位的情况,唤醒之后,线程终不终止,立即还是稍后终止,就把选择全交给程序员自己了。

5. 等待一个线程

有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作,这是我们需要一个方法明确等待线程的结束
可理解为等待一个线程结束!
线程是一个随机调度的过程,等待线程做的事,就是再控制两个线程结束的顺序。

【例1】

public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("hello!!!");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t.start();
        System.out.println("join 之前");

        //此处的join就是让当前的main线程来等待t线程执行结束(等待t的run执行完)
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("join之后");
    }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
执行过程:
t 调用了start()后,t 线程和 main主线程就并发执行,分头行动;
主线程这里打印了“join之前”,同时t线程打印了hello thread;
我们的t线程在执行过程中,主线程并没有打印join之后,而是在join这里等待了一会(发生阻塞block),等待3s之后,t线程执行完了,我们的主线程才会执行后面的 “join之后”;
主线程,等待t线程彻底执行完毕之后,才继续往下执行了。
通过输出,我们也能看出 t 线程肯定比 main 线程先结束。

【例2】

public class ThreadDemo10 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            for (int i = 0; i < 3; i++) {
                System.out.println("hello!!!");
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t.start();

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("join 之前");

        //此处的join就是让当前的main线程来等待t线程执行结束(等待t的run执行完)
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("join之后");
    }
}

JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea
在join前加了一个等待5s钟,此时在执行join的时候,t 已经结束了,所以join不会堵塞,就会立即返回。
JavaEE之多线程编程:2.创建线程及Thread类常见方法(超全!!!),JavaEE,java-ee,python,java,学习方法,intellij idea,开发语言,idea

  • public void join() :无参版本,一直等;
  • public void join(long millis) :指定一个超时时间(最大等待时间),这种是最常见的,一直等很容易又问题。

【总结】
线程没结束,就等待,线程结束了,就立即返回;
总之可以保证这两个线程的返回顺序。

6. 获取当前线程引用

public static Thread currentThread();
返回当前线程对象的引用。

调用这个方法,不需要实例,直接通过类名来调用

	Thread t = new Thread();
	Thread.currentThread();

在哪个线程中调用,就能获取到哪个线程的实例

7. 休眠当前线程

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

public static void sleep(long millis) throws InterruptedException 休眠当前线程 millis
毫秒
public static void sleep(long millis, int nanos) throws InterruptedException 可以更高精度的休眠文章来源地址https://www.toymoban.com/news/detail-756555.html

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(System.currentTimeMillis());
        Thread.sleep(3 * 1000);
        System.out.println(System.currentTimeMillis());
   }
}

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

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

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

相关文章

  • 【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类

    2023年04月08日
    浏览(29)
  • 【JavaEE】_多线程Thread类及其常用方法

    【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日
    浏览(4)
  • 【多线程初阶】Thread类常见方法以及线程的状态

    【多线程初阶】Thread类常见方法以及线程的状态

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

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

    【Java系列】详解多线程(二)——Thread类及常见方法(下篇)

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习Java的一点学习心得,欢迎大家在评论区交流讨论💌 在操作系统中创建线程时,通常会同时创建相应的PCB并将其

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

    【Java系列】详解多线程(二)——Thread类及常见方法(上篇)

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

    2024年02月04日
    浏览(4)
  • 设计模式之多线程分工模式--- Thread-Per-Message模式

    设计模式之避免共享的设计模式Immutability(不变性)模式 设计模式之并发特定场景下的设计模式 Two-phase Termination(两阶段终止)模式 设计模式之避免共享的设计模式Copy-on-Write模式 设计模式之避免共享的设计模式 Thread-Specific Storage 模式 设计模式之多线程版本的if------Guarde

    2024年02月01日
    浏览(7)
  • 【JavaEE】Java中的多线程 (Thread类)

    【JavaEE】Java中的多线程 (Thread类)

    作者主页: paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将基础知识一网打尽,希望可以帮到读者们哦。 其他专栏:《MySQL》《

    2024年02月05日
    浏览(7)
  • JavaEE初阶:多线程 - Thread 类的基本用法

    JavaEE初阶:多线程 - Thread 类的基本用法

    上次我们了解了多线程的五种创建方法,今天来学习Thread的基本用法。 目录 run和start Thread常见的构造方法 Thread的几个常见属性 后台线程 是否存活 线程终止 1.使用标志位 2.使用Thread自带的标志 等待线程 首先需要理解Thread的run和start的区别: run描述了线程要做的工作,star

    2024年02月12日
    浏览(8)
  • 互联网编程之多线程/线程池TCP服务器端程序设计

    互联网编程之多线程/线程池TCP服务器端程序设计

    目录 需求 多线程TCP服务器 线程池TCP服务器 测试 日志模块 多线程TCP服务器(30分): 设计编写一个TCP服务器端程序,需使用多线程处理客户端的连接请求。客户端与服务器端之间的通信内容,以及服务器端的处理功能等可自由设计拓展,无特别限制和要求。 线程池TCP服务器

    2024年02月11日
    浏览(6)
  • Java多线程---线程的创建(Thread类的基本使用)

    Java多线程---线程的创建(Thread类的基本使用)

    本文主要介绍Java多线程的相关知识, Thread的创建, 常用方法的介绍和使用, 线程状态等. 文章目录 前言 一. 线程和Thread类 1. 线程和Thread类 1.1 Thread类的构造方法 1.2 启用线程的相关方法 2. 创建第一个Java多线程程序 3. 使用Runnable对象创建线程 4. 使用内部类创建线程 5. 使用Lamba

    2024年02月03日
    浏览(8)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包