Java多线程之Thread和Runnable以及Callable接口多线程的简单实现(适合小白入门,十分简单)

news2024/11/25 18:51:56

Java多线程之Thread和Runnable

  • 一、介绍
    • 1、程序
    • 2、进程
    • 3、线程
    • 4、整体思路
    • 5、注意
  • 二、Thread
    • 1、思路流程
    • 2、样例代码
    • 3、多线程下载图片
  • 三、Runnable
    • 1、思路流程
    • 2、样例代码
    • 3、多线程下载图片
  • 四、Callable接口(仅作了解)
    • 1、具体流程
    • 2、优点
    • 3、样例
  • 五、两者比较(Thread与Runnable)
    • 1、Thread类
    • 2、Runnable接口
    • 3、并发问题
      • 3.1 问题场景
      • 3.2 样例
  • 六、多线程模拟龟兔赛跑
    • 1、具体代码

一、介绍

1、程序

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。

2、进程

执行程序的一次执行过程,是一个动态的概念,是系统资源分配的单位。

3、线程

通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程。线程是CPU调度和执行的单位

4、整体思路

(1)线程是就是独立的执行路径。
(2)在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程。
(3)main()称之为主线程,为系统的入口,用于执行整个程序。
(4)在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与操作系统紧密相关的,先后顺序不能人为干预。
(5)对同一份资源操作时,会存在资源抢夺的问题,需要加入并发控制。
(6)线程会带来额外的开销。
(7)每个线程在自己工作内存交互,内存控制不当会造成数据不一致。

5、注意

很多的多线程是模拟出来的,真正的多线程是指有多个cpu,即多核,如服务器。如果是模拟出来的多线程,即在一个cpu的情况下,在同一个时间点,cpu只能执行一个代码,因为切换的很快,所以就有同时执行的错觉。

二、Thread

1、思路流程

(1)自定义线程类继承Thread类
(2)重写run( )方法,编写线程执行体
(3)创建线程对象,调用start ( )方法启动线程
(4)线程不一定立即执行,CPU安排调度

2、样例代码

package com.example.multithreading.demo1;

// 创建线程方式一:继承Thread类,重写run()方法,调用start开启线程

// 总结:注意,线程开启不一定立即执行,由CPU调度执行
public class ThreadTest1 extends Thread{

    @Override
    public void run(){
        // run方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("线程" + i);
        }
    }

    public static void main(String[] args){
        // main线程,主线程
        // 创建一个线程对象
        ThreadTest1 threadTest1 = new ThreadTest1();
        // 调用start()方法开启线程
        threadTest1.start();

        for (int i = 0; i < 20; i++) {
            System.out.println("主线程");
        }
    }

}

结果
在这里插入图片描述

3、多线程下载图片

package com.example.multithreading.demo1;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

// 实现多线程同步下载图片
public class ThreadTest2 extends Thread{

    // 网络图片地址
    private String url;
    // 保存的文件名
    private String name;

    public ThreadTest2(String url, String name){
        this.url = url;
        this.name = name;
    }

    // 下载图片线程的执行体
    @Override
    public void run(){
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url, name);
        System.out.println("下载了文件名为:" + name);

    }

    public static void main(String[] args){
        ThreadTest2 threadTest1 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图1.jpg");
        ThreadTest2 threadTest2 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图2.jpg");
        ThreadTest2 threadTest3 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图3.jpg");
        threadTest1.start();
        threadTest2.start();
        threadTest3.start();
    }

}

// 下载器
class WebDownloader{
    // 下载方法
    public void downloader(String url, String name){
        try{
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}


结果
在这里插入图片描述

三、Runnable

1、思路流程

(1)定义一个类实现Runnable接口
(2)实现run( )方法,编写线程执行体
(3)创建线程对象,调用start( )方法启动线程
(因为java单继承的局限性,推荐使用Runnable对象)

2、样例代码

package com.example.multithreading.demo1;

// 创建线程方式2:实现runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class ThreadTest3 implements Runnable{
    @Override
    public void run() {
        // run方法线程体
        for (int i = 0; i < 10; i++) {
            System.out.println("线程" + i);
        }
    }

    public static void main(String[] args){
        // 创建runnable接口的实现类对象
        ThreadTest3 threadTest3 = new ThreadTest3();

        // 创建线程对象,通过线程对象来开启线程代理
        new Thread(threadTest3).start();

        for (int i = 0; i < 20; i++) {
            System.out.println("主线程");
        }
    }
}

结果
在这里插入图片描述

3、多线程下载图片

package com.example.multithreading.demo1;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

public class ThreadTest3_1 implements Runnable{

    // 网络图片地址
    private String url;
    // 保存的文件名
    private String name;

    public ThreadTest3_1(String url, String name){
        this.url = url;
        this.name = name;
    }

    // 下载图片线程的执行体
    @Override
    public void run(){
        WebDownloader2 webDownloader2 = new WebDownloader2();
        webDownloader2.downloader(url, name);
        System.out.println("下载了文件名为:" + name);

    }

    public static void main(String[] args){
        ThreadTest2 threadTest1 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图1.jpg");
        ThreadTest2 threadTest2 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图2.jpg");
        ThreadTest2 threadTest3 = new ThreadTest2("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图3.jpg");
        new Thread(threadTest1).start();
        new Thread(threadTest2).start();
        new Thread(threadTest3).start();
    }

}


// 下载器
class WebDownloader2{
    // 下载方法
    public void downloader(String url, String name){
        try{
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果
在这里插入图片描述

四、Callable接口(仅作了解)

1、具体流程

(1)实现Callable接口,需要返回值类型
(2)重写call方法,需要抛出异常
(3)创建目标对像
(4)创建执行服务:ExecutorService ser = Excecutors.newFixedThreadPool(1);
(5)提交执行:Future result1 = ser.submit(t1);
(6)获取结果:boolean r1 = result1.get()
(7)关闭服务:ser.shutdownNow()

2、优点

可以定义返回值
可以抛出异常

3、样例

package com.example.multithreading.demo2;

import com.example.multithreading.demo1.ThreadTest2;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.*;

public class CallableTest implements Callable<Boolean> {

    // 网络图片地址
    private String url;
    // 保存的文件名
    private String name;

    public CallableTest(String url, String name){
        this.url = url;
        this.name = name;
    }

    // 下载图片线程的执行体
    @Override
    public Boolean call(){
        WebDownloader3 webDownloader = new WebDownloader3();
        webDownloader.downloader(url, name);
        System.out.println("下载了文件名为:" + name);
        return true;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CallableTest t1 = new CallableTest("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图1.jpg");
        CallableTest t2 = new CallableTest("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图2.jpg");
        CallableTest t3 = new CallableTest("http://www.pp3.cn/uploads/allimg/200710/14-200G00Z321.jpg","风景图3.jpg");

        // 创建执行服务
        ExecutorService ser = Executors.newFixedThreadPool(3);

        // 提交执行
        Future<Boolean> r1 = ser.submit(t1);
        Future<Boolean> r2 = ser.submit(t2);
        Future<Boolean> r3 = ser.submit(t3);

        // 获取结果
        boolean rs1 = r1.get();
        boolean rs2 = r2.get();
        boolean rs3 = r3.get();

        System.out.println(rs1);
        System.out.println(rs2);
        System.out.println(rs3);

        // 关闭服务
        ser.shutdownNow();
    }
}

// 下载器
class WebDownloader3{
    // 下载方法
    public void downloader(String url, String name){
        try{
            FileUtils.copyURLToFile(new URL(url), new File(name));
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

结果
在这里插入图片描述

五、两者比较(Thread与Runnable)

1、Thread类

(1)子类继承Thread类具备多线程能力
(2)启动线程:子类对象.start( )
(不建议使用:避免OOP单继承局限性)

ThreadTest1 threadTest1 = new ThreadTest1();
threadTest1.start();

2、Runnable接口

(1)实现接口Runnable具有多线程能力
(2)启动线程:传入目标对象 + Thread对象.start( )
(推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用)

// 一份资源
ThreadTest threadTest = new ThreadTest();
// 多个代理
new Thread(threadTest, "张三").start();
new Thread(threadTest, "李四").start();
new Thread(threadTest, "王五").start();

3、并发问题

3.1 问题场景

多个线程操作同一个资源的情况下,线程不安全,数据会出现紊乱。

3.2 样例

package com.example.multithreading.demo1;

// 多个线程同时操作同一个对像
// 买票
public class ThreadTest4 implements Runnable{

    private int num = 10;

    @Override
    public void run() {
        while (true) {
            if (num <= 0) {
                break;
            }

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            System.out.println(Thread.currentThread().getName() + "-->拿到了第" + num-- + "张票");
        }
    }

    public static void main(String[] args) {
        ThreadTest4 threadTest4= new ThreadTest4();
        new Thread(threadTest4, "张三").start();
        new Thread(threadTest4,"李四").start();
        new Thread(threadTest4,"王五").start();
    }
}

结果
在这里插入图片描述

六、多线程模拟龟兔赛跑

1、具体代码

package com.example.multithreading.demo1;

// 模拟龟兔赛跑
public class TortoiseAndRabbitRace implements Runnable {

    // 定义胜利者
    private static String winner;

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            // 模拟兔子休息
            if(Thread.currentThread().getName().equals("兔子") && i%10==0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }

            // 判断比赛是否结束
            boolean flag = gameOver(i);

            if (flag) {
                break;
            }

            System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");
        }
    }

    // 判断是否完成比赛
    private boolean gameOver(int steps) {
        // 判断是否有胜利者
        if(winner != null){
            // 已经存在胜利者
            return true;
        }
        if (steps >= 100){
            winner = Thread.currentThread().getName();
            System.out.println("winner is " + winner);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        TortoiseAndRabbitRace race = new TortoiseAndRabbitRace();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

结果
在这里插入图片描述

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

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

相关文章

视频编解码 — SVC可伸缩性

目录 SVC分层 时域SVC 空域SVC 在一对多的情况下&#xff0c;根据每个接收端的带宽不同&#xff0c;灵活调整发送码率 SVC分层 第0层&#xff0c;最底层&#xff0c;可以独立进行编解码&#xff0c;不依赖第1&#xff0c;第2层第1层&#xff0c;依赖于第0层第2层&#xff…

Linux中的/proc文件系统详解(C/C++代码实现)

Linux /proc这个特殊的目录包含有关Linux系统的所有详细信息&#xff0c;包括其内核、进程和配置参数。通过研究/proc目录&#xff0c;可以了解Linux命令的工作原理&#xff0c;甚至可以执行一些管理任务。 走进Linux的/proc目录 今天&#xff0c;我们将查看/proc目录并熟悉它…

最新版 苹果 IOS AppStore证书申请全流程 包括p12文件

第一步 登陆开发者网站并进入证书管理页。 辅助工具网站地址&#xff1a;http://www.applicationloader.net/ 第二步 添加【Certificates】证书。在这里插入图片描述 第三步 进入添加页后&#xff0c;根据需求选择。 第四步 选择好环境之后&#xff0c;这里需要选择一个…

GitHub上传本地程序操作的问题解决汇总

1、新建远程仓库 2、提交本地程序到GitHub 完整命令汇总&#xff0c;这些命令的顺序已解决目前Git提交所遇到的下面问题 存在的问题展示部分没贴出来&#xff0c;可以先按命令顺序走一遍流程。 git init //把这个目录变成Git可以管理的仓库git checkout -b main //切换至main默…

如何零基础自学 Python ?听我娓娓道来

如何零基础自学 Python &#xff1f; 前言 今天这篇文章是对初学者的一篇学习资料分享与总结&#xff01; 简单介绍下笔者的自学之路 起初学习 Python 是在 2020 年&#xff0c;那时临近毕业&#xff0c;由于面临着找工作的不确定性&#xff0c;便学习了相关的网络安全知识&…

计组作业笔记【 总线 】

系统总线按传输内容不同分为数据总线&#xff0c;地址总线&#xff0c;控制总线。 片内总线与系统总线是并列关系&#xff0c;与通信总线一同作为总线按功能的分类。 所以选B 总线复用是指一种信号线在不同时间传输不同的信息。 所以该题选A。 当某设备正获得了总线控制权时…

系统安装技能测试

系统安装技能测试 目录 系统安装技能测试 一、制作PE U盘 安装完成之后查看U盘是否有PE 使用制作好的U盘进入PE界面 二、使用虚拟机进入PE界面 虚拟机成功进入PE主界面 三、PE界面进行分区操作 在PE模式下&#xff0c;使用ISO进行系统安装 四、PE系统备份 五、使用PXE进行网克…

Springboot毕业设计毕设作品,微信校园疫情防控小程序设计与实现

功能清单 【后台管理员功能】 关于我们设置&#xff1a;设置学校简介、联系我们、加入我们、法律声明、学校详情 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支持删除 会员列表&#xff1a;查看所有注册会员信…

基于51单片机GPS定位系统设LCD12864显示(程序+原理图+PCB+论文)

资料编号&#xff1a;202 功能介绍&#xff1a; (1).定位功能 GPS通过接收卫星信号&#xff0c;可以准确地定出其所在的位置&#xff0c;位置误差小于10米。利用GPS&#xff0c;在12864上面显示当前位置。 (2).查询时间功能 GPS还可以接收卫星发下来的时间信息&#xff0c;…

【openEuler系列】配置本地yum源

个人名片&#xff1a; 对人间的热爱与歌颂&#xff0c;可抵岁月冗长&#x1f31e; Github&#x1f468;&#x1f3fb;‍&#x1f4bb;&#xff1a;念舒_C.ying CSDN主页✏️&#xff1a;念舒_C.ying 个人博客&#x1f30f; &#xff1a;念舒_C.ying 【openEuler系列】配置本地y…

漏洞深度分析|Apache Fineract 远程代码执行漏洞

项目介绍 Apache Fineract 是一个开源的系统&#xff0c;用于核心银行系统平台化建设。为创业者、金融机构和服务提供商提供了一个可靠、健壮的、可负担得起的金融服务解决方案。 项目地址 https://github.com/apache/fineract 漏洞概述 Apache Fineract 在 1.8.1 之前的版…

NR DCI Format介绍

NR DCI(下行控制信息)与LTE中的DCI类似&#xff0c;均是承载上/下行数据信道的调度信息&#xff08;如PDSCH/PUSCH&#xff09;。 如下表&#xff0c;摘自38212 7.3.1节。其中0-0/0-1承载上行数据信道PUSCH的调度信息。1-0/1-1承载下行数据信道PDSCH的调度信息&#xff0c;加扰…

QT断点调试[通俗易懂]

QT设置断点调试&#xff1a; 1、知道哪里可能出问题2、完全不清楚自己程序bug在哪3、跳过肯定不会出错的地方 前言&#xff1a; 这个东西难道大家不都应该会吗??? 本人用Qt Creator编写Qt的&#xff0c;~ 当然是有大佬用记事本写Qt的hhhh&#xff0c;每个人用IDE或者编辑器…

Python中__init__.py的作用介绍

一、文件__init__.py作用&#xff1a;package / module 的标志 下图的serrors包含这个文件时候&#xff0c;Python会将其当做一个模块&#xff08;module&#xff09;来处理&#xff0c;进而可以使用from serrors import xx方式导入serrors包中的文件或模块。 如图所示&#x…

Linux的IO(初阶)

Linux的IO(初阶) 文章目录Linux的IO(初阶)1.C语言文件IO1.1 C语言文件的(复习)1.2 相对路径与绝对路径(复习)1.3 C语言中文件操作函数(复习)1.4 C语言文件写入方式(复习)1.5 三个默认打开的流1.6 FILE类型的理解2.Linux系统文件IO2.1 打开文件的系统接口函数&#xff1a;open2.…

2023年,学测试还有前途吗?

最近因为疫情等各种原因&#xff0c;大厂裁员&#xff0c;失业等等频频受到关注。 不解释&#xff0c;确实存在&#xff0c;各行各业都很难&#xff0c;但是&#xff0c;说软件测试行业没有前途&#xff0c;我还真不认同&#xff08;不是为培训机构说好话&#xff0c;大环境不…

面向对象编程 上 (1)

目录 学习面向对象内容的三条主线 面向过程与面向对象 面向过程(POP) 与 面向对象(OOP) 面向对象的三大特征 例子&#xff1a;人把大象装进冰箱 面向对象的思想概述 类和对象 面向对象的思想概述 Java类及类的成员 类的语法格式 创建Java自定义类 对象的创建和使用 类…

2022最新的护眼灯怎么选?护眼台灯到底有用吗

众所周知&#xff0c;人眼能看到各种事物&#xff0c;都是由于光线照射到物体身上&#xff0c;然后反射进入人眼成像&#xff0c;但是如果光线不合理或者不合适&#xff0c;那么进入人眼的光线就会对造成巨大的伤害。所以护眼灯到底有没有用&#xff0c;就在于其发出的光线能不…

【python与数据分析】实验十三 北京市空气质量

目录 一、实验内容 二、完成情况 三、数据分析 1.问题描述 2.编程思路 3.程序代码 4.程序运行结果 &#xff08;1&#xff09;2014年-2019年AQI时间序列折线图 &#xff08;2&#xff09;各年AQI折线图、AQI直方图、PM2.5与AQI散点图、空气质量整体情况的饼图 ​&am…

关于虚数与复数

关于虚数与复数1 数的分类1.1 实数域1.2 虚数与复数2 复数的性质及其运算2.1 复平面、大小及辐角2.2 复数四则运算2.3 共轭复数2.4 复数的极坐标表示3 欧拉公式3.1 欧拉公式证明3.2 利用欧拉公式表示极坐标3.3 欧拉公式推导三角函数加法定理4 复数的性质、乘法和除法运算和极坐…