栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中线程的创建及使用

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中线程的创建及使用

目录

Thread类的基本用法

方法1:创建子类,继承Thread

方法2:创建一个类,实现Runnable接口,再创建Runnable实例传递给Thread实例

方法3:使用匿名内部类创建Thread子类对象

方法4:使用匿名内部类创建Runnable子类对象

方法5:使用lambda表达式创建Runnable子类对象

多线程的优势

Thread类及其常见的用法

Thread常见的构造方法

Thread的几个常见的属性

ID

名称

状态

优先级

是否后台线程

是否存活

是否中断

启动线程——start()

中断线程

1.手动设置特殊的标志位,来控制线程是否要执行结束

2.通过 Thread.currentThread().isInterrupted()和Thread.Interrupted()来判定

等待线程

获取当前线程的引用

线程的休眠


当我们用Java进行进行多线程编程的时候,需要创建多个线程,那么怎么创建多个线程呢?在Java标准库中,就提供了一个Thread类,来表示操作线程,Thread类也可以视为是Java标准库提供的API。

在Java中创建好的Thread实例其实和操作系统中的线程是一一对应的关系,操作系统提供了一种关于线程的API(C语言风格),在Java中,对这API进一步包装,就成了Thread类。

Thread类的基本用法

通过Thread类创建线程写法有很多种,其中,最简单的方法就是创建子类,重写run()方法

方法1:创建子类,继承Thread
class MyThread extends Thread{

    //run方法里描述了线程内部要执行哪些代码
    //是在新创建出来的线程中被执行的
    @Override
    public void run() {
        System.out.println("hello,thread");
    }
}

public class Demo1 {
    public static void main(String[] args) {
        Thread t = new MyThread();
        //通过start执行线程,才是真正在系统中创建了线程,执行上面的run操作
        //调用start之前,系统中是没有创建出线程的。
        t.start();
    }
}

其中,我们要注意的是,线程之间是并发执行的,其中,在Java进程中,至少含有一个调用main方法的线程,接下来,我们来举个例子来说明下

首先我们先创建一个MyThread继承Thread,并且重写run() 方法,里面一直每隔一秒循环打印“hello,Thread”,然后我们再在main线程中同理循环打印“hello,main”

接下来,让我们来看下结果,

这里我们会发现,并不是每次都是一下“hello main” 一下“hello Thread”,我们会发现先执行那个线程是具有随机性的,也就是我们常说的线程的抢占式执行。而这个随机执行也会给我们线程编程带来很大的麻烦。

方法2:创建一个类,实现Runnable接口,再创建Runnable实例传递给Thread实例

 通过Runnable类描述任务的内容,再将描述好的任务交个Thread实例。

方法3:使用匿名内部类创建Thread子类对象

方法4:使用匿名内部类创建Runnable子类对象

方法3和方法4都是使用匿名内部类来创建线程,我们通常认为Runnable() 这个方法会好点,这样可以让线程和线程执行的任务更好的解耦(我们一般希望写的代码高内聚,低耦合) Runnable单纯的只是描述了一个任务,至于这个任务怎么执行,他并不关心。

方法5:使用lambda表达式创建Runnable子类对象

 这个方法相当于第四种方法的延伸,使用了lambda表达式代替了Runnable而已。

多线程的优势

多线程的优势是啥呢,自然而然的是提高了代码运行的效率,以前只有一个main线程,现在几个线程,下面我们来用代码展现怎么个提高效率法

让两个数自增十亿次,分别使用一个线程和两个线程

接下来我们来运行下,看看需要花费多长的时间。

花了10798ms,那么接下来我们来看看两个线程会花费多少时间呢

 

我们发现双线程比单线程快了 很多其中join()是啥作用我们后面将会提到

Thread类及其常见的用法

Thread常见的构造方法

 我们前面讲的五种创建线程的方法就是。

Thread的几个常见的属性

ID

线程的唯一标识,不同线程不会重复

名称

是调试工具所要用到的

状态

表示线程所处情况

优先级

调度的优先等级

是否后台线程

这里我们只需要记住一点,JVM在一个进程的所有非后台线程结束后,才会结束运行

是否存活

简单的理解就是run方法时候运行结束了

是否中断

这个问题我们会在后面慢慢提到

启动线程——start()

start()决定了系统是不是真的创建了线程,run()方法只是描述了线程会干什么,而start() 则是一个特殊的方法,内部会在系统中创建线程。

中断线程

如何让一个线程停下来呢?线程停下来的关键,是要让线程对应的run方法执行完(main线程特殊,得main方法执行完)

为了让run方法执行完,我们有以下方法

1.手动设置特殊的标志位,来控制线程是否要执行结束

这里我们设置了一个标志位,main线程修改isQuit当执行时间过了5000ms就停止线程

这种方法并不严谨,我们还有更好的方法

2.通过 Thread.currentThread().isInterrupted()和Thread.Interrupted()来判定

Thread.Interrupted()方法是一个静态方法

Thread.currentThread().isInterrupted()是一个实例方法,其中currentThread()可以获取到当前的线程的实例

 具体用法大家可以看看图片中的讲述

Thread.Interrupted()这个方法判定的标志位是Thread中的静态成员(一个程序中只有一个标志位)而Thread.currentThread().isInterrupted()方法判定的是Thread中的普通成员,每一个示例都能有自己的标志位,所以通常使用这个。

等待线程

这里我们就是来讲解上文用到的join(),首先,调用这个方法的线程是main线程,针对t这个线程使用,就是让main线程等待t线程,当调用join方法后。main线程就会进入阻塞状态,不在继续进行下去,那么怎么才能继续执行下去呢,只有当t线程执行晚了(也就是run方法执行的内容跑完了)通过线程等待,让t线程先结束,main线程在结束,一定程度上,干预了线程的执行次序

但是join()方法属于死等,这并不是很合理,所以,就提供了另一个版本就是我们可以再( )中输入最多等待时间。

获取当前线程的引用

看到标题是不是有点熟悉,对了,这就是前面提到的currentThread(),调用这个方法就可以获得到线程的实例。

线程的休眠

关于线程的休眠,我们前面的例子有使用过,Thread.sleep();当一个线程调用了sleep方法就会进入阻塞队列,而操作系统在调度线程执行的时候,只会从就绪队列中选择合适的PCB到CPU上运行,阻塞队列的就只能干等着,当sleep时间过了,就会重新进入就绪队列。

以上这些就是多线程的基本用法,谢谢大家

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/781642.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号