Java创建线程的四种方式

1.继承Thread类创建线程

  • 定义Thread类的子类,并重写该类的run方法,run()方法的内容就是该线程执行的内容
  • 创建Thread子类的实例,即创建了线程对象。
  • 调用线程对象的start()方法来启动该线程。

    代码演示
public class MyThread extends Thread {

    @Override
public void run() {
// 执行业务逻辑
} public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}

2.通过Runnable接口创建线程类

  • 定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
  • 创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
  • 调用线程对象的start()方法来启动该线程。

    代码演示
public class MyRunnable implements Runnable {
@Override
public void run() {
// 执行业务逻辑
} public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}

3.使用Callable接口和FutureTask类实现创建有返回结果的线程

FutureTask 的出现是为了弥补 Thread 的不足而设计的,可以让程序员跟踪、获取任务的执行情况、计算结果

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

    代码演示
public class MyCallable implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子线程开始计算");
Thread.sleep(2000);
System.out.println("子线程结束计算");
return 100 * 100;
} public static void main(String[] args) throws ExecutionException, InterruptedException {
// 实例化Callable对象
MyCallable myCallable = new MyCallable();
// 使用FutureTask包装
FutureTask<Integer> futureTask = new FutureTask<>(myCallable);
// 创建一个线程执行任务
Thread thread = new Thread(futureTask);
thread.start();
Thread.sleep(1000);
System.out.println("主线程执行");
// 使用get()方法会阻塞主线程,直到子线程执行完成返回结果
int result = futureTask.get();
System.out.println("子线程计算结果: " + result);
} }

执行结果

子线程开始计算
主线程执行
子线程结束计算
子线程计算结果: 10000

4.使用线程池创建线程

为什么要使用线程池呢?

当不是执行一次性任务的时候,如果不使用线程池,那么就要频繁的创建和销毁线程,这是一个比较消耗资源的操作,使用线程池可以灵活的调整线程资源的占用,防止消耗过多的内存

在Java中已经提供了ExecutorSerice、Executors等工具类为我们快速的创建线程池

常用的常见线程的方法有

  • Executors.newFixedThreadPool(int nThreads) --- 创建固定线程数量的线程池
  • Executors.newSingleThreadPool() --- 创建只包含一个线程的线程池
  • Executors.newCachedThreadPool() --- 创建一个可缓存的线程池。如果线程池的当前规模超过了处理需求时,那么就会回收部分空闲的线程(根据空闲时间来回收),当需求增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
  • Executors.newScheduledThreadPool() --- 创建了一个固定长度的线程池,而且以延迟或定时或周期的方式来执行任务,类似于Timer。可应用于重发机制。

Java创建线程的四种方式的更多相关文章

  1. 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...

  2. java多线程(一)创建线程的四种方式

    1.   什么是并发与并行 要想学习多线程,必须先理解什么是并发与并行 并行:指两个或多个事件在同一时刻发生(同时发生). 并发:指两个或多个事件在同一个时间段内发生. 2.   什么是进程.线程 进 ...

  3. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

  4. java创建线程的三种方式及其对比

    第一种方法:继承Thread类,重写run()方法,run()方法代表线程要执行的任务.第二种方法:实现Runnable接口,重写run()方法,run()方法代表线程要执行的任务.第三种方法:实现c ...

  5. AJPFX总结java创建线程的三种方式及其对比

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务.因此把run()方法称为执行 ...

  6. java创建线程的三种方式及其对照

    Java中创建线程主要有三种方式: 一.继承Thread类创建线程类 (1)定义Thread类的子类.并重写该类的run方法,该run方法的方法体就代表了线程要完毕的任务.因此把run()方法称为运行 ...

  7. Java创建线程的第二种方式:实现runable接口

    /*需求:简单的卖票程序多个窗口买票 创建线程的第二种方式:实现runable接口 *//*步骤1.定义类实现Runable接口2.覆盖Runable接口中的run方法    将线程要运行的代码存放在 ...

  8. java创建线程的四种方法

    第一种:  通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runna ...

  9. Java并发——ThreadPoolExecutor线程池解析及Executor创建线程常见四种方式

    前言: 在刚学Java并发的时候基本上第一个demo都会写new Thread来创建线程.但是随着学的深入之后发现基本上都是使用线程池来直接获取线程.那么为什么会有这样的情况发生呢? new Thre ...

随机推荐

  1. 向net core 3.0进击——Swagger的改变

    目录 前言 引入 测试 小结 前言 十一小长假在不知不觉间可都没了,在这个小尾巴的空隙,把这两天鼓捣的net core 3.0升级过程记录一下,首先还是根据之前的顺序一个个补充进来,先从Swagger ...

  2. MongoDB 学习笔记之 索引

    索引: db.media.createIndex({"Tracklist": 1}) 1表示升序 -1表示降序 我们要着重看一下对数组创建索引的情况. 构建一个集合:db.medi ...

  3. 快学Scala 第三课 (定长数组,变长数组, 数组循环, 数组转换, 数组常用操作)

    定长数组定义: val ar = new Array[Int](10) val arr = Array("aa", "bb") 定长数组赋值: arr(0) = ...

  4. 【线性表基础】顺序表和单链表的插入、删除等基本操作【Java版】

    本文表述了线性表及其基本操作的代码[Java实现] 参考书籍 :<数据结构 --Java语言描述>/刘小晶 ,杜选主编 线性表需要的基本功能有:动态地增长或收缩:对线性表的任何数据元素进行 ...

  5. JavaScript事件属性event.target和currentTarget 属性的区别。

    event.target 获取的是触发事件的标签元素 event.currentTarget 获取到的是发起事件的标签元素 一.事件属性:event.target target事件委托的定义:本来该自 ...

  6. Jquery的load加载本地文件出现跨域错误的解决方案

    如果用原生的AJAX是加载本地文件就不会出现错误.当然,这个jquery的load放在服务器上通过http加载还是支持的.也有例外比如在firefox和ie浏览器使用$.ajax加载本地html或tx ...

  7. 谈linux服务器运维需要掌握的技能

    一.linux基础 包括对Linux整体的理解/使用和基本命令 二.运维的命令 运维相关的工具(命令) 三.基础服务 LAMP或LNMP :Apache/Nginx,MySQL,PHP/Python/ ...

  8. 关于Python读写Excel

    关于Excel的读写本人最近看到一篇不错的文章话不多少直接连接https://blog.csdn.net/qq_41185868/article/details/80469355

  9. Jenkins构建Jmeter项目

    1.启动jenkins 2.新建自由风格的项目 定时任务 构建操作 安装HTML Publisher插件 构建后操作 最后保存构建,查看报告

  10. 【C语言笔记】#define与typedef的区别

    1.#define define是预处理指令,在编译时不进行任何检查,只进行简单的替换 宏定义的一般形式为: #define 宏名 字符串 这里所说的字符串是一般意义上的字符序列,不要和C语言中的字符 ...