本文系作者 chaoCode原创,转载请私信并在文章开头附带作者和原文地址链接。

违者,作者保留追究权利。

前言

并发编程在我们日常开发中是时时刻刻都有在用的,只不过大部分的代码底层已经帮我们去做了一些并发编程的安全处理,但是还是有很多情况下需要我们自己去控制,所以我们需要去了解学习并发编程,那么我们一步一步深入的开始学习。

认识java里的线程

Java 程序天生就是多线程的

一个 Java 程序从 main()方法开始执行,然后按照既定的代码逻辑执行,看 似没有其他线程参与,但实际上 Java 程序天生就是多线程程序,因为执行 main() 方法的是一个名称为 main 的线程。

[6] Monitor Ctrl-Break //监控 Ctrl-Break 中断信号的

[5] Attach Listener //内存 dump,线程 dump,类信息统计,获取系统属性等

[4] Signal Dispatcher // 分发处理发送给 JVM 信号的线程

[3] Finalizer // 调用对象 finalize 方法的线程

[2] Reference Handler//清除 Reference 的线程

[1] main //main 线程,用户程序入口

Java线程的创建方式

Thread源码有说明Java线程创建方式,一共有两种。

1.继承Thread类

2.实现Runable接口

当然网上也有人说有第三种,通过实现Callable和Future接口来创建线程。

在Thread类源码中,给出了说明和线程创建方式示例:

Thread 才是 Java 里对线程的唯一抽象,Runable、Callable、Future 只是对任务(业务逻辑) 的抽象。

因此,出现了多种线程创建方式的说法。

1.继承Thread

  • [1] 定义Thread类的子类,并重写该类的run()方法,run()方法被称为线程执行体。
  • [2] 创建Thread子类的实例,即创建线程对象。
  • [3] 调用线程对象的start()方法启动该线程。

2.实现Runnable接口

Thread提供一个带参数的构造方法,我们通过实现Runnable接口再借用这个构造方法就可以获取到根据我们自定义的任务的Thread对象

public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}

  • [1] 定义Runnable接口的实现类,并重写该接口的run()方法。
  • [2] 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
  • [3] 调用线程对象的start()方法来启动该线程。

3.使用Callable和Future

实质也是使用Thread(Runnable target)构造方法,我们通过实现Callable接口实现一个带返回值的任务,然后通过FutureTask类来包装Callable对象,FutureTask这个类实现了RunnableFuture这个接口,但是RunnableFuture这个接口继承了Runnable接口,所以就可以用这个构造方法就可以获取到根据我们自定义的任务的Thread对象。





  • [1] 创建Callable接口的实现类,并实现call()方法,该call()方法作为线程执行体,且该call()方法有返回值。
  • [2] 创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该Future Task对象封装了Callable对象的call()方法的返回值。
  • [3] 使用Future Task对象作为Thread对象的target创建线程对象。
  • [4] 调用线程对象的start()方法来启动该线程。
  • [5] 调用Future Task对象的get()方法来获得子线程执行结束后的返回值。

创建线程的三种方式对比

实现Runnable接口和实现Callable接口的方式基本相同,只是Callable接口里定义的方法有返回值,可以声明抛出异常,大体上可以归结为一大类。这种方式与继承Thread方式之间的主要差别是采用实现Runnable,Callable接口创建多线程:

1、线程类只是实现了Runnable接口或Callable接口,也可以继续实现别的接口,还可以继承其他类。

2、多个线程可以共享同一个Runnable对象,非常适合多个相同线程来处理同一份资源的情况(面向对象)。

3、如果要访问当前线程,必须使用Thread.currentThread()方法,比较复杂。

采用继承Thread类的方式创建线程:

1、因为线程类已经继承了Thread类,所以不能再继承其他父类。

2、如果要访问当前线程,直接使用this即可获得。

通过上面的分析我们发现创建线程的本质就如源码所写那样有两种方式。一个是继承Thread类,一种是实现Runnable接口。

通过对比我们发现,通过接口去创建线程的方式会让我们代码有更大的容错率,有更大的变通空间以及更加的灵活,同时也减少了程序之间的耦合度,毕竟六大原则中的依赖倒置原则的中心思想就是面向接口编程。所以推荐使用实现接口的方式来创建线程。

感谢诸君的观看,文中如有纰漏,欢迎在评论区来交流。如果这篇文章帮助到了你,欢迎点赞关注。

并发编程——认识java里的线程的更多相关文章

  1. java并发编程笔记(三)——线程安全性

    java并发编程笔记(三)--线程安全性 线程安全性: ​ 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现 ...

  2. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  3. Java并发编程(您不知道的线程池操作)

    Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...

  4. Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    目录 引言 四种线程池 newCachedThreadPool:可缓存的线程池 newFixedThreadPool:定长线程池 newSingleThreadExecutor:单线程线程池 newS ...

  5. 【Java并发编程】之二:线程中断

    [Java并发编程]之二:线程中断 使用interrupt()中断线程 ​ 当一个线程运行时,另一个线程可以调用对应的Thread对象的interrupt()方法来中断它,该方法只是在目标线程中设置一 ...

  6. java并发编程笔记(七)——线程池

    java并发编程笔记(七)--线程池 new Thread弊端 每次new Thread新建对象,性能差 线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或者OOM 缺 ...

  7. java并发编程笔记(五)——线程安全策略

    java并发编程笔记(五)--线程安全策略 不可变得对象 不可变对象需要满足的条件 对象创建以后其状态就不能修改 对象所有的域都是final类型 对象是正确创建的(在对象创建期间,this引用没有逸出 ...

  8. 小谈Java里的线程

    今天,我们来谈一谈Java里的线程. 一.进程与线程的基本概念 大家可能没听过线程这个概念,但是相信,用计算机的朋友都听过进程这个概念.打开电脑的任务管理器,我们就可以看到许多进程.它们主要分为三类, ...

  9. 【并发编程】Java并发编程传送门

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. [并发编程系列博客传送门](https://www.cnblogs.com/54 ...

随机推荐

  1. Kubernetes ConfigMap详解,多种方式创建、多种方式使用

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 配置是程序绕不开的话题,在Kubernetes中使用ConfigMap来配置,它本质其实就是键值对.本文讲解如何 ...

  2. 精尽Spring Boot源码分析 - 序言

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  3. hdu1233 最小生成树Prim算法和Kruskal算法

    Prim算法 时间复杂度:O(\(N^2\),N为结点数) 说明:先任意找一个点标记,然后每次找一条最短的两端分别为标记和未标记的边加进来,再把未标记的点标记上.即每次加入一条合法的最短的边,每次扩展 ...

  4. mapboxgl 互联网地图纠偏插件(二)

    前段时间写的mapboxgl 互联网地图纠偏插件(一)存在地图旋转时瓦片错位的问题. 这次没有再跟 mapboxgl 的变换矩阵较劲,而是另辟蹊径使用 mapboxgl 的自定义图层,重新写了一套加载 ...

  5. 整理!企业选择好用的CRM系统的要点(上)

    随着市场经济的发展,对任何行业的企业来说,客户都是非常重要的一个部分.CRM系统帮助企业做到以客户为中心,它可以根据客户的具体要求进行跟进和反馈,在很大程度上提高公司的客户服务水平和客户满意度,进而提 ...

  6. AcWing 1289. 序列的第k个数

    BSNY 在学等差数列和等比数列,当已知前三项时,就可以知道是等差数列还是等比数列. 现在给你 整数 序列的前三项,这个序列要么是等差序列,要么是等比序列,你能求出第k项的值吗. 如果第k项的值太大, ...

  7. Java核心基础第3篇-Java流程控制

    Java流程控制 本章一起来探讨下Java的流程控制语句.主要从以下几个方面展开: Java分支语句 Java循环语句 Java其实和其他任何的开发语言一样,分支语句和循环语句是必不可少的,有个这两个 ...

  8. CentOS-Docker搭建Rancher(单点)

    参考官方安装说明 服务器准备 节点服务器的硬件配置,可根据实际情况依据该表自行选择. 规模集群节点CPU内存 小 最多5个 高达50 2 8 GB 中 最多15个 最多200 4 16 GB 大 高达 ...

  9. bugku本地包含

    重点:eval()函数有执行漏洞 函数本身作用,把字符串当成php代码计算. 所以自然想到,可以把我们的写好的php代码写入进去. 题目又暗示在本地,想到flag.php了,所以想办法把文件里面的内容 ...

  10. linux驱动之获取设备树信息

    上一篇文章学习了字符设备的注册,操作过的小伙伴都知道上一篇文章中测试驱动时是通过手动创建设备节点的,现在开始学习怎么自动挂载设备节点和设备树信息的获取,这篇文章中的源码将会是我以后编写字符驱动的模板. ...