线程的三种创建方式你get了吗?(代码片段)

李子捌 李子捌     2022-12-05     510

关键词:

  • 备战2022春招或暑期实习,祝大家每天进步亿点点!Java并发编程Day4
  • 本篇总结的是 如何在Java中避免创建不必要的对象,后续会每日更新~
  • 关于《我们一起学Redis》、《我们一起学HarmonyOS》等知识点可以查看我的往期博客
  • 相信自己,越活越坚强,活着就该逢山开路,遇水架桥!生活,你给我压力,我还你奇迹!

目录

1、Thread

2、Runnable和Thread

3、Callable和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、Callable和Thread

Callable和Runnable一样,也是一个函数式接口,二者的区别非常明显,Runnable中run方法没有返回值,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、三者对比

创建线程的方式有三种,Thread、Runnable+Thread、Callable+FutureTask+Thread;这三者如何选择呢?

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

5、注意项

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

👇🏻 关注公众号 获取更多资料👇🏻

mybatis延迟加载的三种加载方式深入,你get了吗?

延迟加载  延迟加载对主对象都是直接加载,只有对关联对象是延迟加载。  延迟加载可以减轻数据库的压力,  延迟加载不可是一条SQL查询多表信息,这样构不成延迟加载,会形成直接加载。  延迟加载分为三种类型... 查看详情

并发编程(壹):创建线程的三种方式及其对比(代码片段)

创建线程的三种方式及其对比1.继承Thread类(1).继承Thread类。并重写run()方法,该方法无参数,无返回值;(2).创建子类实例,并实例化对象;(3).通过start()方法启动,注意:不是通过run()方法启动。publicclassThreadDemoextendsThreadpublicvoid... 查看详情

大数据必学java基础(七十六):创建线程的三种方式(代码片段)

文章目录创建线程的三种方式一、继承Thread类二、实现Runnable接口三、实现Callable接口创建线程的三种方式一、继承Thread类在学习多线程之前,以前的代码是单线程的吗?不是,以前也是有三个线程同时执行的。现在... 查看详情

java创建线程的三种方式,同步锁的实现synchronized,lock(代码片段)

一、继承Thread类创建通过继承Thread并且重写其run()方法,通过调用start()方法即可执行线程方法。写法1:publicclassMyThreadextendsThread@Overridepublicvoidrun()for(inti=0;i<15;i++)System.out.println(getName()& 查看详情

java——多线程高并发系列之创建多线程的三种方式(threadrunnablecallable)(代码片段)

...)方法)写在前面历时一个星期,终于整完了Java多线程高并发这个系 查看详情

49多线程创建的三种方式之继承thread类(代码片段)

继承Thread类创建线程在java里面,开发者可以创建线程,这样在程序执行过程中,如果CPU空闲了,就会执行线程中的内容。使用Thread创建线程的步骤:1.自定义一个类,继承java.lang包下的Thread类2.重写run方法3.将要在线程中执行的... 查看详情

springboot静态获取bean的三种方式,你学会了吗?

点击关注公众号,实用技术文章及时了解来源:blog.csdn.net/showchi/article/details/97005720注意:调用者要被spring管理目录方式一 注解@PostConstruct方式二 启动类ApplicationContext方式三手动注入ApplicationContext方式一 注解@... 查看详情

阿里巴巴建议的线程池创建方式,你用上了吗?(代码片段)

...5327873Executor是不建议的Executors类为我们提供了各种类型的线程池,经常使用的工厂方法有:public static ExecutorService newSingleThreadExecutor 查看详情

使用tpl取回task中的运行结果的三种方式(代码片段)

...:TPL(Task ParallelLibrary)任务并行库使用Task类执行多线程操作要比直接使用自己手工创建Thread效率高很多。默认情况下,TPL使用线程池中的线程执行Task,但是工作结束之后,调用者线程怎么取回执行线程的工作结果呢?这里... 查看详情

java多线程实现的三种方式(代码片段)

文章目录实现多线程方式一:继承Thread类方法介绍实现步骤代码演示思考问题实现多线程方式二:实现Runnable接口Thread构造方法实现步骤代码演示实现多线程方式三:实现Callable接口方法介绍实现步骤代码演示三种实现方式... 查看详情

python创建虚拟环境的三种方式(代码片段)

Python创建虚拟环境的三种方式比较Python创建虚拟环境的三种方式首先:为什么需要虚拟环境?PipenvvsVirtualenvvsConda1.Virtualenv2.Pipenv3.Conda参考资料Python创建虚拟环境的三种方式首先:为什么需要虚拟环境?在使用Python... 查看详情

创建servlet的三种方式(代码片段)

第一种方式,实现Servlet接口1packagecom.example.servlet;23importjava.io.IOException;45importjavax.servlet.Servlet;6importjavax.servlet.ServletConfig;7importjavax.servlet.ServletException;8importjavax.servlet.Ser 查看详情

golang主线程让子线程退出的三种方式(代码片段)

在golang中,主go程告知子go程退出有三种方式,建议用后面两种方式一:全局变量方式packagemainimport( "fmt" "sync" "time")varwgsync.WaitGroupvarexitbool//零值为false//方式1全局变量funcmode1() fmt.Println 查看详情

golang主线程让子线程退出的三种方式(代码片段)

在golang中,主go程告知子go程退出有三种方式,建议用后面两种方式一:全局变量方式packagemainimport( "fmt" "sync" "time")varwgsync.WaitGroupvarexitbool//零值为false//方式1全局变量funcmode1() fmt.Printl 查看详情

java-多线程-创建线程的三种方式

JAVA-多线程-创建线程的三种方式并发:同一时间只有一条指令在执行,多个进程的指令被快速轮换执行。并行:同一时间有多条指令在多个处理器上运行。进程:每个运行中的程序就是一个进程。线程:线程(Thread)也被称为轻... 查看详情

创建线程的三种方式的对比?

(1)采用实现Runnable、Callable接口的方式创建多线程。优势是:线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。在这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同线... 查看详情

锁和多线程:线程创建3种方式(代码片段)

线程 锁Synchronized  1.线程创建2.线程安全 搞明白线程锁和多线程系列1.线程创建线程创建常见的三种方式:继承Thread类实现Runnable接口实现Callable接口第三种方式有异步调用效果,类似js中的ajax可以接收返回值,其余两... 查看详情

react创建组件的三种方式及区别(代码片段)

React创建组件具体的三种方式:1.函数式定义的无状态组件2.es5原生方式React.createClass定义的组件3.es6形式的extendsReact.Component定义的组件 虽然有三种方式可以定义React组件,但是它们有什么不同呢?什么情况下应该使用哪种定... 查看详情