本文系作者 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. Dagger2入门,以初学者角度

    2016-12-21 更新:添加@Subcomponent注解以及Lazy与Provider的使用,本文基本完结!如果有好的建议请提出,感谢大家的支持,谢谢 依赖注入 Dagger2是Android中 ...

  2. docker安装mysql镜像和容器

    下拉镜像 docker pull mysql/mysql-server:5.5 后面的mysql标签是版本号,是可选择的,有: 5.5 5.6 5.7 8.0 创建mysql5.5的容器 docker ...

  3. 基于js的姓名校验

    // 姓名校验 isRightName: function(name) { var reg = /^[a-zA-Z\u4E00-\u9FA5\uF900-\uFA2D\u00B7\u2022\u009 ...

  4. 南京大学计算机基础 X64函数调用和链接器原理和可重定位的文件.o

    一. 1.函数调用差别 X64的函数调用,和X86函数调用区别,在于参数的传递不一样了,X64的参数传递不在依靠栈来传,而是寄存器,不过还是具有局限性的 比如只能允许六个寄存器来传,分别是RDI,RS ...

  5. Leetcode No.121 Best Time to Buy and Sell Stock(c++实现)

    1. 题目 1.1 英文题目 You are given an array prices where prices[i] is the price of a given stock on the it ...

  6. asp.net mvc中的路由

    [Route] 路由 [Route("~/")] 忽略路由前缀 [Route("person/{id:int}")] 路由内联约束 [Route("h ...

  7. Django基础-01篇

    一.Django介绍 flask,FastApi是轻量级服务端开发框架 Django是重量级服务端开发框架 ORM:封装了数据库操作 form:校验请求数据 安装Django: pip install ...

  8. PYTHON 错误提示:ModuleNotFoundError: No module named 'cv2'

    ModuleNotFoundError: No module named 'cv2' 解决方法: pip install -i https://pypi.tuna.tsinghua.edu.cn/si ...

  9. Spring总结之AOP

    一.Spring AOP简介(百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是 Spring 框架中的一个重 ...

  10. win10实现倒计时锁屏,休眠

    @ECHO OFF&SETLOCAL ENABLEDELAYEDEXPANSION SET /a s=10+1FOR /l %%i in (1,1,!s!) do ( SET /a s-=1 ...