线程创建的三种方式及区别
本文首发地址:https://www.dawnsite.cn/archives/256.html
文章目录
- 一. 创建方式
- 1. 继承Thread类
- 2. 实现Runnable接口
- 3. 实现Callable接口
- 二. 创建线程三种方式的优缺点
- 1. 继承Thread类
- 2. 实现Runnable接口
- 3. Runnable和Callable的区别
- 4. start()和run()的区别
- 4. start()和run()的区别
一. 创建方式
1. 继承Thread类
- 定义Thread类的子类,并重写该类的run方法。
- 创建Thread子类的实例,即创建了线程对象。
- 调用线程对象的start()方法来启动线程。
package Thread;/*1.继承Thread类2.重写run()方法3.调用start()方法开启线程*/
public class TestThread extends Thread {@Overridepublic void run() {//重写run()方法for (int i = 0; i < 10; i++) {System.out.println("小明在厨房做饭");}}public static void main(String[] args) {//创建Thread子类的实例TestThread testThread = new TestThread();//调用start()方法开启线程testThread.start();for (int i = 0; i < 200; i++) {System.out.println("小红在客厅打王者");}}
}
当多线程没有开启时,代码只执行主线程里面main()方法的代码,当开启线程后,经过cpu调度后开始执行(线程开启后不一定立即执行)
运行结果:
2. 实现Runnable接口
- 实现Runnable接口,并重写该接口的run()方法。
- 创建Runnable实现类的实例,并用该实例作为Thread的target来创建Thread对象,Thread对象才是真正的线程对象。
- 调用线程对象的start()方法来启动线程。
package Thread;/*1.实现Runnable接口2.重写run()方法3.创建Runnable接口实现类实例,并将该实例放入Thread的target来创建Thread对象4.调用start()方法开启线程*/
public class TestRunnable implements Runnable {@Overridepublic void run() {//重写run()方法for (int i = 0; i < 10; i++) {System.out.println("小明在厨房做饭");}}public static void main(String[] args) {//创建Runnable接口实现类实例TestRunnable testRunnable = new TestRunnable();//该实例放入Thread的target来创建Thread对象//调用start()方法开启线程
// Thread thread = new Thread(testRunnable);
// thread.start();new Thread(testRunnable).start();for (int i = 0; i < 200; i++) {System.out.println("小红在客厅打王者");}}
}
执行结果:
3. 实现Callable接口
- 实现Callable接口并指定返回值,然后实现call()方法。
- 创建Callable实现类的实例,使用FutureTask包装类来包装Callable对象。
- 使用FutureTask对象作为Thread对象的target创建并启动新线程。
- 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
package Thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;/*1.实现Callable接口。2.重写call()方法。3.创建Callable接口实现类实例,使用FutureTask包装类来包装Callable实例对象。4.使用FutureTask对象作为Thread的target来创建Thread对象。5.调用start()方法开启线程。6.调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。*/
public class TestCallable implements Callable<Boolean> {@Overridepublic Boolean call() throws Exception {//重写call()方法for (int i = 0; i < 10; i++) {System.out.println("小明在厨房做饭");}return true;}public static void main(String[] args) throws ExecutionException, InterruptedException {//创建Callable接口实现类实例TestCallable testCallable = new TestCallable();//使用FutureTask包装类来包装Callable实例对象FutureTask<Boolean> task = new FutureTask<>(testCallable);//使用FutureTask对象作为Thread的target来创建Thread对象//调用start()方法开启线程new Thread(task).start();for (int i = 0; i < 200; i++) {System.out.println("小红在客厅打王者");}//调用FutureTask对象的get()方法来获得子线程执行结束后的返回值System.out.println(task.get()); //获取call()的返回值。若调用时call()方法未返回,则会阻塞线程等待返回值}
}
执行结果:
二. 创建线程三种方式的优缺点
1. 继承Thread类
优点:编写简单,如果需要访问当前线程,无需使用Thread.currentThread()方法,直接使用this即可。
缺点:java是单继承的,故无法再继承其他类。
2. 实现Runnable接口
优点:线程类只是实现了Runnable接口,还可以继承其他类。这种情况下,可以多个线程共享同一个目标对象,所以非常适合多个相同线程来处理同一份资源的情况,从而可以将cpu代码和数据分开,形成清晰的模型,较好地体现了面向对象的思想。
缺点:编程稍微复杂,如果需要访问当前线程,必须使用Thread.currentThread()方法。
3. Runnable和Callable的区别
Runnable规定的方法是run(),Callable规定的是call()。
Runnable的任务执行后无返回值,Callable的任务执行后有返回值。
call()方法可以抛出异常,run()方法不可以,因为run()方法本身没有抛出异常,所以自定义的线程类在重写run()方法的时候也无法抛出异常。
运行Callable任务可以拿到一个Future对象,表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。通过Future对象可以了解任务执行情况,可取消人物的执行,还可获取执行结果。
4. start()和run()的区别
start()方法用来,开启线程,但是线程开启后并没有立即执行,他需要获取cpu的执行权才可以执行。
run()方法是由jvm创建完本地操作系统级线程后回调的方法,不可以手动调用(否则就是普通方法)。
任务执行情况,可取消人物的执行,还可获取执行结果。
4. start()和run()的区别
start()方法用来,开启线程,但是线程开启后并没有立即执行,他需要获取cpu的执行权才可以执行。
run()方法是由jvm创建完本地操作系统级线程后回调的方法,不可以手动调用(否则就是普通方法)。
线程创建的三种方式及区别相关推荐
- 一心多用多线程-线程创建的三种方式
第一次了解java线程机制,记录一下线程启动的三种方式. 1.通过继承Thread类调用一个线程 public class Thread1 extends Thread{@Overridepublic ...
- 线程生命周期以及线程创建的三种方式
1. 线程生命周期 线程生命周期图 新建状态(New) 当线程对象创建后,即进入新建状态,如:Thread t = new MyThread(); 就绪状态(Runnable) 当调用线程对象的sta ...
- 创建线程的第三种方式---JDK8新特性
创建线程的第三种方式-JDK8新特性 实现Callable接口,创建线程 Runnable和Callable接口的不同 1.Callable可以返回一个类型V,而Runnable不可以,也就是说Cal ...
- 创建线程的第三种方式:实现Callable接口(含部分源码解析)
创建线程的第三种方式--实现Callable接口 package com.lqy.Multithreading; import java.util.concurrent.Callable; impor ...
- JUC-多线程(5.获得线程的第三种方式)学习笔记
文章目录 获得线程的第三种方式 : Callable接口 1. 前言 1. 获得多线程的方法几种? 2. 以下两种获得线程的方式的异同 2. 使用 1. 重写 call 方法 2.创建线程 3.获取返 ...
- 创建线程的三种方式及区别
一:创建线程的三种方式: 1.继承Thread类 2.实现Runnable接口 3.使用Callable接口 二:创建线程的具体实现步骤: 1.继承Thread类 (1).先继承 Thread类,并且 ...
- React创建组件的三种方式及其区别
React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归:具体的三种方式: 函数式定义的无状态组件 es5原生方式React.createClass定义的组件 es6形式的ext ...
- java 创建数组的三种方式及区别
创建数组的三种方式:其实分为2类,一种是静态的创建,如方式一.一种是动态的创建,只不过根据写法的不同分为方式二和方式三: // 数组初始化的三种方式//1.声明,分配空间并赋值int[] arr0 = ...
- java多线程学习一、线程介绍、线程创建的3种方式、lambda创建方式、线程状态、线程示例:12306买票和银行取钱
文章目录 前言 一.线程简介 1.概述 2.进程.线程 区别 在这里插入图片描述 3. 核心概念 二. 线程创建 1.概述 2. 第一种方式继承Thread 1) 继承Thread 2) 示例:下载图 ...
- java实现线程安全的三种方式
前言 一个程序在运行起来的时候会转换成进程,通常含有多个线程.通常情况下,一个进程中的比较耗时的操作(如长循环.文件上传下载.网络资源获取等),往往会采用多线程来解决. 比如现实生活中,银行取钱问题. ...
最新文章
- [Node.js]回调函数
- java 调用父类的变量_java创建子类对象设置并调用父类的变量操作
- Chrome 技术篇-json查看,json格式化,JSONView插件
- 【PHP】Sublime下PHP网站开发指南
- LeetCode每日一题 142. 环形链表 II
- 毛笔笔锋算法IOS版
- BGP——路由抖动惩罚机制(讲解+配置)
- 蔚来ES8正式交付售价46.8万元起 与Model系相比扛打吗?
- 接收 go run main.go 后面的参数_厦门油泥水三相离心分离机功能和参数
- 全国大学生数学建模竞赛中,哈工大被禁用 MATLAB!
- tomcat中server.xml文件解析
- 自带内网穿透的文件同步工具Syncthing介绍
- VS中安装.nupkg文件
- 信息展示类图表设计指南:10个必须遵循的步骤
- 玩转 Spring Boot 应用篇(序列号生成器服务实现)
- 华为2019秋招笔试题2
- 计算机强行删除用户密码,如果忘记了笔记本计算机的开机密码该怎么办? Win7强制删除登录密码...
- aviary 图片编辑器
- 家庭备忘记事便签软件哪个实用?
- Xadmin-Xadmin的安装与配置(Django2.0+python3.6)
热门文章
- linux win10五笔码表,Win10五笔助手下载_WubiLex微软五笔助手下载免费版9.9.6.0 - 系统之家...
- 做了6年的Java,java简历包装项目经验
- 【GlobalMapper精品教程】009:DSM过滤植被和房屋并生成等高线案例教程
- hadoop、spark、hive、solr、es与YDB在车辆即席分析上的对比分析
- Wpf 初学---01设计一个优美的注册界面
- 【复习】数学分析知识点梳理【思维导图】
- vue 下载文件,文件损坏无法打开
- 一些易被忽视且难度较高的Web前端面试题汇总
- 安卓手机通电自动开机,自动执行脚本,断电关机,连接电源手机自动开机,断电关机
- jQuery实现选择“学科门类”、“学科大类(一级学科)”、“专业”(二级学科)实现三级联动