多线程的实现方式

news2024/9/23 3:24:43

点击链接返回标题->

Java线程的学习-CSDN博客


第一种方式,继承Thread类

Thread类是java.lang包下的类,是多线程经常需要使用的类。

①通过自定义子类去继承Thread类,并重写其中的run()方法。

class myThread extends Thread {//自定义子类myThread继承Thread类

    @Override
    public void run() {//重写run()方法
        for (int i = 1; i <= 100; i++) {
            System.out.println(getName() + "打印了" + i);//
        }
    }
}

②用自定义子类实例化对象t,这个对象t就是一个线程,并调用对象t的start()方法,启动该线程。

myThread t1 = new myThread();//实例化对象,线程t1
myThread t2 = new myThread();//实例化对象,线程t2

t1.start();//启动线程t1

t2.start();//启动线程t2

③可以调用对象t的setName()方法,给线程命名,如果不命名,默认线程名为Thread-0、Thread-1...调用getName()方法获取当前线程名

t1.setName("线程1");//设置线程t1的名字
t2.setName("线程2");//设置线程t2的名字

示例代码——

public class Main {
    public static void main(String[] args) {
        myThread t1 = new myThread();//实例化对象,线程t1
        myThread t2 = new myThread();//实例化对象,线程t2

        t1.setName("线程1");//设置线程t1的名字
        t2.setName("线程2");//设置线程t2的名字

        t1.start();//启动线程t1
        t2.start();//启动线程t2
    }
}

class myThread extends Thread {//自定义子类myThread继承Thread类

    @Override
    public void run() {//重写run()方法
        for (int i = 1; i <= 100; i++) {
            System.out.println(getName() + "打印了" + i);//
        }
    }
}

 这里展现出部分运行结果,可以看到,cpu在执行这段代码时,在线程1和线程2之间反复切换(执行线程1还是线程2,是随机的!)


 第二种方式,实现Runnable接口

Runnable接口是java.lang包下的接口

在大多数情况下,如果只打算重写run()方法而不使用其他Thread方法,则应使用Runnable接口

①通过自定义子类去实现Runnable接口,并重写其中的run()方法。

class MyRun implements Runnable {
    public void run() {
        for (int i = 1; i <= 100; i++) {
            System.out.println("MyThread类的run()方法在运行");
        }
    }
}

②用自定义子类实例化对象mr,这个mr现在还不是线程,而是线程要执行的任务。

MyRun mr = new MyRun();

③用Thread类实例化对象t,并传入mr实现有参构造,这个t才是线程,用start()方法启动线程。

//Thread类传入MyRun的对象通过有参构造实例化对象
Thread t1 = new Thread(mr);
Thread t2 = new Thread(mr);

t1.start();
t2.start();

④同样的,可以调用对象t的setName()方法,给线程命名,但是——因为这个自定义子类是实现Runnable接口而不是继承Thread类,所以在自定义子类中不能直接调用Thread类的getName()方法获取线程名字。解决方法是,在这个自定义类中用Thread类中的一个静态方法Thread.currentThread(),获取当前线程的实例化对象,然后调用这个对象的方法。

class MyRun implements Runnable {
    public void run() {
        Thread th = Thread.currentThread();//获取当前线程的实例化对象
        for (int i = 1; i <= 100; i++) {
            System.out.println(th.getName() + "MyThread类的run()方法在运行");
        }
    }
}

示例代码——

public class Main {
    public static void main(String[] args) {
        MyRun mr = new MyRun();
        //Thread类传入MyRun的对象通过有参构造实例化对象
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);

        //设置线程名字
        t1.setName("线程1");
        t2.setName("线程2");

        //启动线程
        t1.start();
        t2.start();
    }
}

class MyRun implements Runnable {
    public void run() {
        Thread th = Thread.currentThread();//获取当前线程的实例化对象
        for (int i = 1; i <= 100; i++) {
            System.out.println(th.getName() + "MyThread类的run()方法在运行");
        }
    }
}

部分运行结果—— 


 第三种方式,实现Callable接口

我们发现前两种方式都是通过重写run()方法的形式来实现,但这个run()方法的返回值却是void类型的,也就是说,我们无法通过返回值获取多线程中的运行结果。

假如线程A执行一个运算任务,线程B需要获取线程A的运算结果,这该如何实现呢?

Callable接口是java.util.concurrent包下的接口,它的特点是可以获取到多线程运行的结果。

①通过自定义子类去实现Callable接口,并重写call()方法,call()方法必须声明抛出异常。

有关Java异常详见本篇->Java异常-CSDN博客

class mycall implements Callable<Integer> {//这个<Integer>是声明泛型的返回值是整数
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}

②用自定义子类实例化对象mc,这个mc现在还不是线程,而是线程要执行的任务。

mycall mc = new mycall();

③用FutureTask类去实例化对象ft,这个对象用来管理线程的返回值

FutureTask<Integer> ft = new FutureTask<>(mc);

 ④用Thread类创建线程对象t,传入管理线程任务的对象ft实现有参构造,并调用对象t的start()方法启动线程。

Thread t1 = new Thread(ft);

Thread t2 = new Thread(ft);

t1.start();

t2.start();

⑤调用ft的get()方法获取对应线程的运行结果,这个结果可以作为数据按实际需求使用。

Integer res1 = ft.get();

Integer res2 = ft.get();

System.out.println(res1 + res2);

示例代码——

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

public class Main {
    public static void main(String[] args) throws ExecutionException, InterruptedException {//此处方法需要注意声明抛出异常
        mycall mc = new mycall();
        FutureTask<Integer> ft = new FutureTask<>(mc);
        Thread t1 = new Thread(ft);
        Thread t2 = new Thread(ft);
        t1.start();
        t2.start();
        Integer res1 = ft.get();
        Integer res2 = ft.get();
        System.out.println(res1 + res2);
    }
}

class mycall implements Callable<Integer> {//这个<Integer>是声明泛型的返回值是整数

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum += i;
        }
        return sum;
    }
}


三种方式的对比

对于后两种方式, 不能直接使用Thread类中的方法,解决方法为:先调用Thread类的静态方法currentThread(),获取当前线程的实例化对象,再用该实例化对象来调用需要使用的方法。


线程的常用成员方法将在下篇介绍,敬请期待!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1244697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

hive return code 40000 from org.apache.hadoop.hive.ql.exec.MoveTask解决思路

参考学习 https://github.com/apache/hive/blob/2b57dd27ad61e552f93817ac69313066af6562d9/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java#L47 为啥学习error code 开发过程中遇到以下错误&#xff0c;大家觉得应该怎么办&#xff1f;从哪方面入手呢&#xff1f; 1.百…

51单片机利用I/O口高阻状态实现触摸控制LED灯

51单片机利用I/O口高阻状态实现触摸控制LED灯 1.概述 这篇文章介绍使用I/O口的高阻状态实现一个触摸控制LED灯亮灭的实验。该实验通过手触摸P3.7引脚&#xff0c;改变电平信号控制灯的亮灭。 2.实验过程 2.1.实验材料 名称型号数量单片机STC12C20521LED彩灯无1晶振12MHZ1电…

【git】使用ssh

前言 git之前一直使用https&#xff0c;因为很方便随时随地都可以用。最近把代码托管到GitHub&#xff0c;使用https就使用不了。后面听同事说GitHub使用ssh是没问题的&#xff0c;就想着尝试一下。 git ssh配置 设置用户名和邮箱 git config --global use.name username g…

一条Update语句的执行过程是怎样的?

先看第一个问题&#xff0c;这里做个简单描述 &#xff0c;因为我们着重还是看Update MySQL执行一条Select语句是怎么运行的&#xff1f; 这个问题大家在面试的时候大家都背过类似的题&#xff0c;而且网上也有很多答案&#xff0c;这里分享一个大致流程介绍&#xff0c;关于…

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示

通过ros系统中websocket中发送sensor_msgs::Image数据给web端显示 #include <ros/ros.h> #include <signal.h> #include <sensor_msgs/Image.h> #include <message_filters/subscriber.h> #include <message_filters/synchronizer.h> #include &…

国外网站文章或网页采集翻译为中文

采集国外网站的文章或网页数据&#xff08;例如英文&#xff0c;西班牙语&#xff0c;法语等&#xff09;&#xff0c;怎么快速批量翻译为中文&#xff1f; 可以使用简数采集器来实现&#xff0c;支持自动翻译&#xff0c;同时翻译为多种语言&#xff08;不仅中文&#xff09;…

(C++)反转字符串中的单词

愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/reverse-w…

分享一个课程卡样式

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 广告打完&#xff0c;我们进入正题&#xff0c;先看效果&#xff1a; 废话不多&#xff0c;上源码&#xff1a; <body><h3 c…

Java飞翔的鸟游戏

一.准备工作 首先创建一个新的Java项目命名为“飞翔的鸟”&#xff0c;并在src中创建一个包命名为“com.qiku.bird"&#xff0c;在这个包内分别创建4个类命名为“Bird”、“BirdGame”、“Column”、“Ground”&#xff0c;并向需要的图片素材导入到包内。 二.代码呈现 …

Spring-jdbcTemplate-配置数据库连接池,配置文件方式beans.xml

1、jdbc.properties jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql:///studb jdbc.userroot jdbc.pwd123456 2、beans.xml <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans&…

给sprite上增加刷光动效

游戏引擎 —— cocos creator 3.52 此动效给动态修改尺寸的图片增加一层刷光的效果&#xff0c;直接贴代码 CCEffect %{techniques:- passes:- vert: sprite-vs:vertfrag: sprite-fs:fragdepthStencilState:depthTest: falsedepthWrite: falseblendState:targets:- blend: tr…

仿ChatGPT对话前端页面(内含源码)

仿ChatGPT对话前端页面&#xff08;内含源码&#xff09; 前言布局样式和Js部分关键点全部源码 前言 本文主要讲解如何做出类似ChatGPT的前端页面。具体我们的效果图是长这样&#xff0c;其中除了时间是动态的之外&#xff0c;其他都是假数据。接下来让我们从布局和样式的角度…

Redis打包事务,分批提交

一、需求背景 接手一个老项目&#xff0c;在项目启动的时候&#xff0c;需要将xxx省整个省的所有区域数据数据、以及系统字典配置逐条保存在Redis缓存里面&#xff0c;这样查询的时候会更快; 区域数据字典数据一共大概20000多条,&#xff0c;前同事直接使用 list.forEach…

Django框架之中间件

目录 一、引入 二、Django中间件介绍 【1】什么是Django中间件 【2】Django中间件的作用 【3】示例 三、Django请求生命周期流程图 四、Django中间件是Django的门户 五、Django中间件详解 六、中间件必须要掌握的两个方法 (1) process_request (2) process_respon…

支持对协议和会话分享动作进行授权,新增API Key白名单功能,JumpServer堡垒机v3.9.0发布

2023年11月20日&#xff0c;JumpServer开源堡垒机正式发布v3.9.0版本。在这一版本中&#xff0c;JumpServer对授权功能进行了优化&#xff0c;增加了对“会话分享”及“资产协议”的配置&#xff0c;方便管理员以更细的颗粒度对各种资源进行控制&#xff1b;针对使用API Key与J…

教你看现货黄金实时报价

现货黄金投资市场上的交易软件众多&#xff0c;很多人不知道选择什么软件好&#xff0c;但选择主流软件MT4&#xff0c;基本就可以满足投资者不同的需求。本文为大家讲讲&#xff0c;为什么有那么多的投资者&#xff0c;都选择通过MT4获取实时的行情报价。 现货黄金市场波动激烈…

Linux中flask项目开启https访问

1.下载阿里云免费证书 2.项目添加https配置 3.服务器开启https访问 3.1 重新安装OpenSSL 3.2.重新安装Python 上一次已经讲过Linux安装部署Python: Linux安装Python3.10与部署flask项目实战详细记录,今天记录一下Python项目如何支持https访问…

免费开源 GPU池化软件 | (AI人工智能训练平台、AI人工智能推理平台)全套源码

GPU池化软件 | (AI人工智能训练平台、AI人工智能推理平台) 讨论群v:&#x1f680;18601938676 一、AI人工智能开发-------------面临的问题和挑战 1. GPU管理难题 1.1 资源管理难&#xff1a;算力资源昂贵&#xff0c;但是缺乏有效管理&#xff0c;闲置情况严重。 1.2 用户…

RabbitMQ快速学习之WorkQueues模型、三种交换机、消息转换器(SpringBoot整合)

文章目录 前言一、WorkQueues模型消息发送消息接收能者多劳 二、交换机类型1.Fanout交换机消息发送消息接收 2.Direct交换机消息接收消息发送 3.Topic交换机消息发送消息接收 三、编程式声明队列和交换机fanout示例direct示例基于注解 四、消息转换器总结 前言 WorkQueues模型…

【2023-11-23】生成A~Z编号

生成A~Z编号 需要生成 A~Z的编号&#xff0c;当新的编号超过Z时&#xff0c;从A1开始&#xff0c;依次为B1 C1一直至Z1,如此循环。 最大支持字母为Z&#xff0c;超过后以添加数字后缀的形式标记 简单代码 默认从A开始循环 function getLimitNumber(_total) {var num 0var …