JAVA开启线程的三种方式

2023-05-16

目录

继承Thread类

实现Runnable接口

通过Callable和Future创建对象


继承Thread类

  1. 定义Thread类的子类,并重写run()方法
  2. 创建该子类的实例,即创建了线程对象
  3. 调用线程对象的start()方法类启动该线程
package com.cn.thread;

/**
 * 1.定义Thread类的子类,并重写run()方法
 */
public class ThreadDemoOne extends Thread {
    @Override
    public void run() {
        System.out.println("启动线程。。。");
    }

    public static void main(String[] args) {
//      2.创建该子类的实例,即创建了线程对象
        ThreadDemoOne threadDemoOne = new ThreadDemoOne();
//      3.调用线程对象的start()方法类启动该线程
        threadDemoOne.start();
    }
}

实现Runnable接口

  1. 定义了一个实现Runnable接口的类,并重写run()方法
  2. 创建该类的实例,并将此实例作为Thread类的target来创建Thread对象,该Thread对象是真正的线程对象
  3. 调用该线程对象的start()方法启动该线程 
package com.cn.thread;

/**
 * 1.定义了一个实现Runnable接口的类,并重写run()方法
 */
public class ThreadDemoTwo implements Runnable {

    public void run() {
        System.out.println("启动线程。。。");
    }

    public static void main(String[] args) {
//      2.创建该类的实例,并将此实例作为Thread类的target来创建Thread对象,该Thread对象是真正的线程对象
        ThreadDemoTwo threadDemoTwo = new ThreadDemoTwo();
        Thread thread = new Thread(threadDemoTwo);
//      3.调用该线程对象的start()方法启动该线程
        thread.start();
    }
}

通过Callable和Future创建对象

  1. 定义一个实现Callable接口的类,并实现call()方法,该call方法将作为线程执行体,并且有返回值
  2. 创建该类的实例
  3. 创建FutureTask的实例,即使用FutrueTask类来包装Callable对象
  4. 将FutureTask的实例作为Thread的target创建并启动新线程
  5. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值 
package com.cn.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 1.定义一个实现Callable接口的类,并实现call()方法,该call方法将作为线程执行体,并且有返回值
 */
public class ThreadDemoThree implements Callable<Integer> {

    public Integer call() {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            sum += i;
        }
        return sum;
    }

    public static void main(String[] args) {
//          2.创建ThreadDemoThree对象
        Callable<Integer> myCallable = new ThreadDemoThree();
//          3.创建FutureTask的实例,即使用FutrueTask类来包装Callable对象
        FutureTask<Integer> ft = new FutureTask<Integer>(myCallable);
//          4.将FutureTask的实例作为Thread的target创建并启动新线程
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + " " + i);
            if (i == 30) {
                Thread thread = new Thread(ft);   //FutureTask对象作为Thread对象的target创建新的线程
                thread.start();                      //线程进入到就绪状态
            }
        }

        System.out.println("主线程for循环执行完毕..");
//          5.调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
        try {
            int sum = ft.get();            //取得新创建的新线程中的call()方法返回的结果
            System.out.println("sum = " + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}

首先,我们发现,在实现Callable接口中,此时不再是run()方法了,而是call()方法,此call()方法作为线程执行体,同时还具有返回值!在创建新的线程时,是通过FutureTask来包装MyCallable对象,同时作为了Thread对象的target。那么看下FutureTask类的定义:

public class FutureTask<V> implements RunnableFuture<V> {
     
    //....
    
}


public interface RunnableFuture<V> extends Runnable, Future<V> {
    
   void run();
   
}

于是,我们发现FutureTask类实际上是同时实现了Runnable和Future接口,由此才使得其具有Future和Runnable双重特性。通过Runnable特性,可以作为Thread对象的target,而Future特性,使得其可以取得新创建线程中的call()方法的返回值。

执行下此程序,我们发现sum = 4950永远都是最后输出的。而“主线程for循环执行完毕..”则很可能是在子线程循环中间输出。由CPU的线程调度机制,我们知道,“主线程for循环执行完毕..”的输出时机是没有任何问题的,那么为什么sum =4950会永远最后输出呢?

原因在于通过ft.get()方法获取子线程call()方法的返回值时,当子线程此方法还未执行完毕,ft.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值。

上述主要讲解了三种常见的线程创建方式,对于线程的启动而言,都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA开启线程的三种方式 的相关文章

  • dto层与model层的区别

    Model层是面向业务的 xff0c 我们是通过业务来定义Model的 而DTO是面向界面UI的 xff0c 是通过UI的需求来定义的 通过DTO我们实现了表现层与Model之间的解耦 xff0c 表现层不引用Model 如果开发过程中我们
  • 常用命令 ctags的使用

    1 命令ctags ctags的功能 xff1a 扫描指定的源文件 xff0c 找出其中所包含的语法元素 xff0c 并将找到的相关内容记录下来 ctags R 扫描当前目录及所有子目录 xff08 递归向下 xff09 中的源文件 结合v
  • idea 导入 maven依赖包的源码

    修改maven的版本为maven2 xff08 之前是maven3 xff09 勾选自动下载
  • Error java: 无法访问javax.servlet.ServletException 找不到javax.servlet.ServletException的类文件

    pom xml文件添加下面依赖 xff1a lt dependency gt lt groupId gt javax lt groupId gt lt artifactId gt javaee api lt artifactId gt lt
  • 如何看Spring源码

    https blog csdn net qq 27529917 article details 79209846 想要深入的熟悉了解Spring源码 xff0c 我觉得第一步就是要有一个能跑起来的极尽简单的框架 xff0c 下面我就教大家搭
  • AnnotationAwareOrderComparator

    https blog csdn net zhuqiuhui article details 82974026 AnnotationAwareOrderComparator简介 xff1a AnnotationAwareOrderCompar
  • HandlerInterceptor

    对SpringMVC有所了解的人肯定接触过HandlerInterceptor拦截器 xff0c HandlerInterceptor接口给我们提供了3个方法 xff1a xff08 1 xff09 preHandle 在执行control
  • spring源码阅读记录

    spring启动方式之一 xff1a 通过实现servlet3 0的Servlet容器初始化接口javax servlet ServletContainerInitializer xff0c 调用onStartup方法来启动项目 无web
  • IDEA将外来的jar包导入到maven项目中

    https blog csdn net baidu 32492845 article details 79173893 很多时候项目因为方便运行或者maven的dependency中到 xff0c 我们会直接将现有的jar包导入到项目中 x
  • intellij idea Jdk编译设置

    1 修改 Language level 和 Module SDK 选择 File gt project Structure gt Modules xff0c 选择项目修改 Sources 选项卡下的 Language level 及 Dep
  • JDK8新特性:函数式接口@FunctionalInterface的使用说明

    https blog csdn net aitangyong article details 54137067 我们常用的一些接口Callable Runnable Comparator等在JDK8中都添加了 64 FunctionalIn
  • JDK8新特性:接口的静态方法和默认方法

    https blog csdn net aitangyong article details 54134385 在jdk8之前 xff0c interface之中可以定义变量和方法 xff0c 变量必须是public static fina
  • 如何使用github和git进行团队合作开发(队友和owner的仓库连接)

    折腾了两天终于搞懂了一个团队开发一个项目 xff0c 在github和git下该如何操作 xff0c 本文就简单总结一下我的过程吧 xff0c 希望对大家有帮助 1 首先确定一个项目拥有者 xff0c 即你们一个团队的项目都上传到他的git
  • springboot源码阅读一

    目录 入口 SpringApplication 部分参数初始化 SpringApplication initialize方法 SpringApplication run方法 StopWatch java awt headless系统设定 入
  • idea Maven项目找不到相关依赖包(红色波浪线)

    方案一 修改pom 配置文件 xff0c 讲标红的依赖先删除 xff0c 并点击reimport 之后重新加上出错的依赖 xff0c 再reimport 方案二 从删除本地仓库中的文件目录 xff0c 强制 maven 重新下载该包
  • 自定义FailureAnalyzer

    目录 介绍 代码示例 介绍 FailureAnalyzer是一种很好的方式在启动时拦截异常并将其转换为易读的消息 xff0c 并将其包含在FailureAnalysis中 Spring Boot为应用程序上下文相关异常 JSR 303验证等
  • 自动配置故障排除

    目录 官网文档 71 2 Troubleshoot auto configuration 翻译 71 2 自动配置故障排除 官网文档 71 2 Troubleshoot auto configuration The Spring Boot
  • 在环境或应用程序上下文启动之前对其进行自定义

    目录 官网文档 71 3 Customize the Environment or ApplicationContext before it starts 翻译 71 3 在环境或应用程序上下文启动之前对其进行自定义 官网文档 71 3 C
  • 构建ApplicationContext层次结构(添加父上下文或根上下文)

    目录 官网文档 71 4 Build an ApplicationContext hierarchy adding a parent or root context 翻译 71 4 构建ApplicationContext层次结构 xff0
  • 创建非Web应用程序

    目录 官方文档 71 5 Create a non web application 翻译 71 5 创建非Web应用程序 官方文档 71 5 Create a non web application Not all Spring appli

随机推荐

  • Customizing the Banner

    自定义方式 1 设置banner txt文件 默认读取根路径 xff0c 也可以通过banner location属性指定文件位置 xff0c 并且可以通过banner charset 默认是UTF 8 属性设置txt文件编码 在banne
  • isAssignableFrom方法浅析

    源码 Determines if the class or interface represented by this 64 code Class object is either the same as or is a superclas
  • @SuppressWarnings("serial")

    比如有个类实现了java io Serialize接口 xff1a package com onede4 test public class TestSerial implements java io Serializable 如果代码仅仅
  • angularJs中将字符串转换为HTML格式

    首先定义一个filter xff1a filter 39 to trusted 39 39 sce 39 function sce return function text return sce trustAsHtml text 2 htm
  • 如何在IDEA启动多个Spring Boot工程实例

    目录 只需要三步走即可 在IDEA上点击Application右边的下三角 弹出选项后 xff0c 点击Edit Configuration 打开配置后 xff0c 将默认的Single instance only 单实例 的钩去掉 通过修
  • springboot学习记录一

    概述 Spring Boot可以轻松创建独立的 xff0c 生产级的基于Spring的应用程序 xff0c 您可以 只要运行 我们对Spring平台和第三方库采取了自以为是 武断 的观点 xff0c 因此您可以最少的手忙脚乱 慌乱 开始 大
  • Java8 如何正确使用 Optional

    引用 http www importnew com 26066 html Optional是Java8提供的为了解决null安全问题的一个API 善用Optional可以使我们代码中很多繁琐 丑陋的设计变得十分优雅 这篇文章是建立在你对Op
  • git清除本地账户

    删除保存在本地的git账户 git credential manager uninstall 缓存账户 git config global credential helper wincred
  • 服务注册与发现eureka

    目录 eureka server pom xml文件添加依赖 启动类添加注解 64 EnableEurekaServer appication yml配置文件 访问界面 eureka client pom xml文件添加依赖 启动类添加注解
  • 服务消费者RestTemplate+Ribbon

    目录 简介 pom xml添加依赖 通过 64 LoadBalanced注解表明这个restRemplate开启负载均衡的功能 这样 restTemplate访问接口就可以实现负载均衡功能了 简介 spring cloud有两种服务调用方式
  • 服务消费者Feign

    Feign简介 Feign是一个声明式的伪Http客户端 xff0c 它使得写Http客户端变得更简单 使用Feign xff0c 只需要创建一个接口并注解 它具有可插拔的注解特性 xff0c 可使用Feign 注解和JAX RS注解 Fe
  • 熔断器Hystrix

    目录 概述 在ribbon使用断路器 断路器简介 添加依赖 启动类添加注解 64 EnableHystrix 方法上添加 64 HystrixCommand 关闭service hi服务 Feign中使用断路器 开启断路器功能 修改 64
  • Hystrix Dashboard (断路器:Hystrix 仪表盘)

    目录 pom xml添加依赖 启动类添加 64 EnableHystrixDashboard注解 浏览器访问 pom xml添加依赖 lt dependency gt lt groupId gt org springframework bo
  • nexus3私服搭建

    应用场景 maven库分为本地仓库和远程仓库 包括私服和中央仓库 xff09 公司自己设立 xff0c 只为公司内部共享使用 xff0c 同时减少外部访问和下载频率等 使用Nexus搭建私服 下载 官网链接 xff1a https www
  • Java多种方法实现等待所有子线程完成再继续执行

    简介 在现实世界中 xff0c 我们常常需要等待其它任务完成 xff0c 才能继续执行下一步 Java实现等待子线程完成再继续执行的方式很多 我们来一一查看一下 Thread的join方法 该方法是Thread提供的方法 xff0c 调用j
  • nexus3私服使用

    使用功能包括 代理中央仓库 Snapshot包的管理 Release包的管理 第三方Jar上传到Nexus上 从nexus下载依赖jar 代理中央仓库 只要在PMO文件中配置私服的地址即可 获取jar包信息走私服 xff0c 然后私服保存的
  • springboot开启的两种方式

    目录 继承spring boot starter parent项目 导入spring boot dependencies项目依赖 Spring Boot依赖注意点 属性覆盖只对继承有效 资源文件过滤问题 使用Spring Boot很简单 x
  • SpringBoot 中怎么禁用某些自动配置特性?

    有 3 种方法 如果我们想禁用某些自动配置特性 xff0c 可以使用 64 EnableAutoConfiguration 或 64 SpringBootApplication 注解的 exclude 属性来指明 方案1 xff0c 下面的
  • vim用法和技巧

    引子 研发线上使用最多的编辑器 xff0c 就是vi 无论是最快查看某个文件内容 xff0c 还是快速编辑某个文件 xff0c vi都能帮上忙 软件世界貌似有一些非常长寿的东西 xff0c vi算是一个 本篇文章聚焦的是研发线上最常用的一些
  • JAVA开启线程的三种方式

    目录 继承Thread类 实现Runnable接口 通过Callable和Future创建对象 继承Thread类 定义Thread类的子类 xff0c 并重写run xff08 xff09 方法创建该子类的实例 xff0c 即创建了线程对