Java线程的三种创建方式

目录
  • 1、Thread
  • 2、Runnable和Thread
  • 3、Runnable和Thread
  • 4、三者对比
  • 5、注意项

1、Thread

继承Thread类,并重写run方法

class ThreadDemo1 extends Thread {

  @Override

  public void run() {

    log.info("{}", Thread.currentThread().getName());

  }

}

线程启动方式:

ThreadDemo1 t1 = new ThreadDemo1();

t1.setName("t1");

t1.start();

简便写法:

Thread t1 = new Thread() {

    @Override

    public void run() {

        log.info("{}", Thread.currentThread().getName());

    }

};

t1.setName("t1");

t1.start();

2、Runnable和Thread

Thread类的构造函数支持传入Runnable的实现类

public Thread(Runnable target) {

    init(null, target, "Thread-" + nextThreadNum(), 0);

}

Thread(Runnable target, AccessControlContext acc) {

    init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);

}

Runnable是一个函数式接口(FunctionalInterface

@FunctionalInterface

public interface Runnable {

    // 没有返回值

    public abstract void run();

}

因此需要创建类实现Runnable接口,重写run方法

class ThreadDemo2 implements Runnable {

    @Override

    public void run() {

        log.info("{}", Thread.currentThread().getName());

    }

}

简便写法:

Thread t2 = new Thread(() -> log.info("{}", Thread.currentThread().getName()), "t2");

t2.start();

3、Runnable和Thread

CallableRunnable一样,也是一个函数式接口,二者的区别非常明显,Runnablerun方法没有返回值,Callable中的run方法有返回值(可以通过泛型约束返回值类型)。因此在需要获取线程执行的返回值时,可以使用Callable

@FunctionalInterface

public interface Callable<V> {

    // 带返回值

    V call() throws Exception;

}

Thread的构造函数中,并没有看到Callable,只有Runnable

此时需要一个可以提交Callable给Thread的类,这类就是FutureTask;FutureTask实现类Runnable接口。

并且FutureTask提供了传入Callable的构造函数

public FutureTask(Callable<V> callable) {

    if (callable == null)

        throw new NullPointerException();

    this.callable = callable;

    this.state = NEW;       // ensure visibility of callable

}

因此可以通过FutureTask传入Callable实现,再将FutureTask传给Thread即可

ThreadDemo3 implements Callable<Integer> {

    @Override

    public Integer call() throws Exception {

        log.info("{}", Thread.currentThread().getName());

        return 1998;

    }

}
// Callable 实现类

ThreadDemo3 callable = new ThreadDemo3();

// 通过Callable创建FutureTask

FutureTask<Integer> task = new FutureTask(callable);

// 通过FutureTask创建Thread

Thread t3 = new Thread(task, "t3");

t3.start();

简便写法:

Thread t3 = new Thread(new FutureTask<Integer>(() -> {

    log.info("{}", Thread.currentThread().getName());

    return 1998;

}), "t3");

t3.start();

4、三者对比

创建线程的方式有三种:

ThreadRunnable+ThreadCallable+FutureTask+Thread;这三者如何选择呢?

  • 首先在实际的开发过程中,我们不会直接创建线程,因为频繁创建和销毁线程开销比较大,此外不利于管理和释放,因此项目中都是通过设计线程池来管理线程资源
  • ThreadRunnable+Thread相比,Runnable+Thread将线程的创建和任务模块解耦了,代码设计更加灵活,此外更加利于任务的提交,更方便和线程池结合使用
  • Callable+FutureTask+Thread适用于需要获取线程返回结果的场景

5、注意项

文中多次使用thread.start();需要注意的是,调用线程的start()方法表示启动线程,但是线程是否执行并不确定,这需要操作系统调度,线程分配到CPU执行时间片才能执行。多核CPU下多个线程同时启动,线程之间交替执行,执行顺序是不确定的。

到此这篇关于Java线程的三种创建方式的文章就介绍到这了,更多相关Java线程创建方式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java实现/创建线程的几种方式小结

    进程与线程 进程可以简单理解成一个可执行程序例如.exe,在Windows中的任务管理器中可以查看每一个进程,进程是一次程序的执行,是程序在数据集合上运行的过程,是系统资源调度的一个单位.进程主要负责向操作系统申请资源.然而一个进程中,多个线程可以共享进程中相同的内存或文件资源.线程就是一个进程一个程序要完成所依赖的子任务,这些子任务便可以看作是一个线程. 第一种方式继承Thread类 从java源码可以看出Thread类本质上实现了Runnable接口的实例类,代表了线程的一个线程的实例,启动

  • Java创建线程及配合使用Lambda方式

    目录 一.创建线程三种方式 1.1 继承Thread类创建线程类 1.2 通过Runnable接口创建线程类 使用Lambda表达式 1.3 通过Callable和Future创建线程 使用Lambda表达式 二.创建线程的三种方式的对比 2.1 实现Runnable.Callable接口的方式创建多线程 2.2 继承Thread类的方式创建多线程 2.3 Runnable和Callable的区别 一.创建线程三种方式 1.1 继承Thread类创建线程类 定义Thread类的子类,并重写该类的

  • Java创建多线程的8种方式集合

    目录 1.继承Thread类,重写run()方法 2.实现Runnable接口,重写run() 3.匿名内部类的方式 4.带返回值的线程(实现implements Callable<返回值类型>) 5.定时器(java.util.Timer) 6.线程池的实现(java.util.concurrent.Executor接口) 7.Lambda表达式的实现(parallelStream) 8.Spring实现多线程 1.继承Thread类,重写run()方法 //方式1 package cn.i

  • 很多人竟然不知道Java线程池的创建方式有7种

    目录 前言 什么是线程池? 线程池使用 1.FixedThreadPool 2.CachedThreadPool 3.SingleThreadExecutor 4.ScheduledThreadPool 5.SingleThreadScheduledExecutor 6.newWorkStealingPool 7.ThreadPoolExecutor 线程池的执行流程 线程拒绝策略 自定义拒绝策略 究竟选用哪种线程池? 前言 根据摩尔定律所说:集成电路上可容纳的晶体管数量每 18 个月翻一番,因

  • java中线程池最实用的创建与关闭指南

    目录 前言 线程池创建 只需要执行shutdown就可以优雅关闭 执行shutdownNow关闭的测试 总结 前言 在日常的开发工作当中,线程池往往承载着一个应用中最重要的业务逻辑,因此我们有必要更多地去关注线程池的执行情况,包括异常的处理和分析等. 线程池创建 避免使用Executors创建线程池,主要是避免使用其中的默认实现,那么我们可以自己直接调用ThreadPoolExecutor的构造函数来自己创建线程池.在创建的同时,给BlockQueue指定容量就可以了. private stat

  • Java线程创建的四种方式总结

    多线程的创建,方式一:继承于Thread类 1.创建一个继承于Thread类的子类 2.重写Thread类的run()--->将此线程执行的操作声明在run()中 3.创建Thread类的子类的对象 4.通过此对象调用start(): start()方法的两个作用: A.启动当前线程 B.调用当前线程的run() 创建过程中的两个问题: 问题一:我们不能通过直接调用run()的方式启动线程 问题二:在启动一个线程,遍历偶数,不可以让已经start()的线程去执行,会报异常:正确的方式是重新创建一

  • Java基础之多线程方法状态和创建方法

    目录 Java之线程的五大状态及其常用方法(六个状态还有timed_wating超时等待) 1.线程的五大状态及其转换 2.设置或获取多线程的线程名称的方法 3.线程休眠------sleep()方法 4.线程让步------yield()方法 5. 等待线程终止------join()方法 6. 线程停止 7. 线程等待------wait()方法 8. 线程唤醒-------notify()方法 9. notifyAll()方法 JAVA多线程有哪几种实现方式? 1. 继承Thread类 2

  • 如何在Java中创建线程通信的四种方式你知道吗

    目录 1.1 创建线程 1.1.1 创建线程的四种方式 1.1.2 Thread类与Runnable接口的比较 1.1.3 Callable.Future与FutureTask 1.2 线程组和线程优先级 1.3 Java线程的状态及主要转化方法 1.4 Java线程间的通信 1.4.1 等待/通知机制 1.4.2 信号量 1.4.3 管道 总结 1.1 创建线程 1.1.1 创建线程的四种方式 [1]继承Thread类 [2]实现Runnable接口 [3]实现Callable,获取返回值 [

  • Java线程的三种创建方式

    目录 1.Thread 2.Runnable和Thread 3.Runnable和Thread 4.三者对比 5.注意项 1.Thread 继承Thread类,并重写run方法 class ThreadDemo1 extends Thread { @Override public void run() { log.info("{}", Thread.currentThread().getName()); } } 线程启动方式: ThreadDemo1 t1 = new ThreadDe

  • java中进程与线程_三种实现方式总结(必看篇)

    一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程是指处于运行过程中的程序,并且具有一定的独立功能.进程是系统进行资源分配和调度的一个单位.当程序进入内存运行时,即为进程. 进程的三个特点: 1:独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每一个进程都有自己独立的地址空间,没有进程本身的运行,用户进程不可以直接访问其他进程的地址空间. 2:

  • Java多线程中线程的两种创建方式及比较代码示例

    1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行.当程序作为一个应用程序运行时,java解释器为main()方法启动一个线程. 2.并行与并发: (1)并发:在单处理器系统中,多个线程共享CPU时间,而操作系统负责调度及分配资源给它们. (2)并行:在多处理器系统中,多个处理器可以同时运行多个线程,这些线程在同一时间可以同时运行,而不同于并发,只能多个线程共享CP

  • java数组的三种扩容方式以及程序实现详解

    因为数组是在内存中连续的一段存储空间,所以数组一旦被创建,空间就固定了,长度是不能扩增的. 数组的长度是固定的,如果需要扩充**,必须创建新数组,原数组的长度要复制到新数组中 .** java中,数组类型的变量传值的时候,事实上传递的是数组的地址 . Java数组扩容的原理 1)Java数组对象的大小是固定不变的,数组对象是不可扩容的. 2)利用数组复制方法可以变通的实现数组扩容. 3)System.arraycopy()可以复制数组. 4)Arrays.copyOf()可以简便的创建数组副本.

  • Java spring的三种注入方式详解流程

    目录 设置Spring的作用域 自动注入 @Primary Qualifier @ComponentScan不同的配置对性能的影响 懒加载 三种注入方式 字段注入(IDEA 会提示不推荐) 字段注入的bean类外部不可见 循环依赖问题 构造器注入(官方推荐) set方法注入 设置Spring的作用域 或者使用枚举值设置 单例和多里使用场景 自动注入 @Primary 一个接口有多个实现被spring管理吗,在依赖注入式,spring会不知道注入哪个实现类就会抛出NoUniqueBeanDefin

  • Java栈的三种实现方式(完整版)

    java什么是栈 系统中的堆.栈和数据结构堆.栈不是一个概念.可以说系统中的堆.栈是真实的内存物理区,数据结构中的堆.栈是抽象的数据存储结构. 栈:实际上就是满足后进先出的性质,是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除. 栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器.但缺点是,存在栈中的数据大小与生存期必须是确定的,缺乏灵

  • 详解解Django 多对多表关系的三种创建方式

    目录 1.方式一:自动创建 2.方式二:纯手动创建 3.方式三:半自动创建 1.方式一:自动创建 # django orm 自动帮我们创建第三张表,我的app名字是app01, 表名为:app01_book_authors # 这种方式可以让Django迅速的帮我们建一张关系表出来,好处是可以通过这张表进行跨表查询,坏处是一张虚拟表,拓展性差. # 书籍表 class Book(models.Model): name = models.CharField(max_length=32) autho

  • Java线程(Thread)四种停止方式代码实例

    1.正常的程序启动,停止 2.使用退出标记,一般程序在run()方法后,线程会正常结束. 但是有一些伺服线程还在运行,他们运行时间较长,只有当外部条件满足时,他们才会停止.实现如下: public class ThreadCease extends Thread{ private volatile boolean exit = false; public void run(){ while(!exit){ //停止后做的事情~ } } 3.使用线程(Thread)自带的isInterrupted

  • Java的线程与进程以及线程的四种创建方式

    目录 问题描述 case代码截图 数据库DO controller定义 dao定义 mapper实现 mysql相关properties配置 数据库数据 测试结果 具体错误信息 解决 总结 问题描述 这里我想测试某个与springboot相关的问题,结果在搭建mybatis时,发现没有成功从数据库中获取数据,报错信息为 com.mysql.cj.exceptions.DataConversionException: Unsupported conversion from LONG to java

  • Java定时任务的三种实现方式

    前言 现代的应用程序早已不是以前的那些由简单的增删改查拼凑而成的程序了,高复杂性早已是标配,而任务的定时调度与执行也是对程序的基本要求了. 很多业务需求的实现都离不开定时任务,例如,每月一号,移动将清空你上月未用完流量,重置套餐流量,以及备忘录提醒.闹钟等功能. Java 系统中主要有三种方式来实现定时任务: Timer和TimerTask ScheduledExecutorService 三方框架 Quartz 下面我们一个个来看. Timer和TimerTask 先看一个小 demo,接着我

随机推荐