首页 > 编程语言 >“Java多线程编程:从Thread到Runnable再到Callable的深入探索“

“Java多线程编程:从Thread到Runnable再到Callable的深入探索“

时间:2024-07-04 17:29:49浏览次数:18  
标签:Runnable Java Thread 接口 Callable 线程 多线程 public

1 什么是进程?

通俗地解释为:计算机中正在执行的一个程序实例。进程它是系统分配资源的基本单位

想象一下,你的电脑就像是一个大工厂,而每一个进程就像是这个工厂里的一条生产线或者一个工作小组,它们各自独立地运行着不同的任务,但同时又受到整个工厂(即操作系统)的管理和调度。

2 什么是线程?

线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以拥有多个线程,这些线程共享该进程的地址空间和系统资源,但各自拥有独立的执行栈和程序计数器,以便能够独立地执行指令序列。

我们原来写的代码都是单线程。

3 为什么实现多线程?

3.1 进程与线程的关系

可以想象一个工厂代表一个进程,而工厂内的工人则代表进程中的线程

+------------------------+  
|           工厂         |  <-- 进程  
| (操作系统分配的资源)   |  
|  +-----+-----+-----+   |  
|  |工人1|工人2|工人3|   |  <-- 线程  
|  +-----+-----+-----+   |  
|        ...             |  
|  +-----+-----+-----+   |  
|  |工人N|空闲位置|空闲位置|   <-- 更多线程或可扩展性  
|  +-----+-----+-----+   |  
+------------------------+

在这个模型中,每个工人(线程)都在工厂(进程)内独立工作,但他们共享工厂的资源(如工具、原材料等),这些资源相当于进程中的内存、文件句柄等。

3.2 多线程的优势

提高CPU利用率

+------------------------+  
|           工厂         |  
| (CPU核心)              |  
|  +-----+-----+-----+   |  
|  | CPU1| CPU2| CPU3|   |  <-- 多核CPU  
|  +-----+-----+-----+   |  
|  |工人1|工人2|工人3|   |  <-- 每个CPU核心运行一个线程  
|  +-----+-----+-----+   |  
+------------------------+

在多核CPU上,每个核心可以独立运行一个线程,从而提高了CPU的利用率。当某个线程等待I/O操作时,CPU可以切换到另一个线程继续工作

4 java中如何创建多线程

java中提供了三种实现多线程的方式:

第一种: 继承Thread类

第二种: 实现Runnable接口

第三种: 实现Callable接口
4.1继承Thread

这是创建线程的最基本方式之一。通过继承Thread类并重写其run()方法,你可以定义线程执行的任务。然后,创建该类的实例并调用其start()方法来启动线程。

// 继承Thread类  
class MyThread extends Thread {  
    @Override  
    public void run() {  
        // 在这里编写线程要执行的任务  
        System.out.println("线程运行中:" + Thread.currentThread().getName());  
    }  
}  
  
public class ThreadExample {  
    public static void main(String[] args) {  
        MyThread t1 = new MyThread();  
        t1.start(); // 启动线程  
    }  
}
4.2 实现Runnable接口

实现Runnable接口是另一种创建线程的方式。这种方式相比继承Thread类更加灵活,因为Java不支持多重继承,但可以实现多个接口。通过实现Runnable接口,你可以将线程的任务与线程的实现分离。然后,创建Thread类的实例,将实现了Runnable接口的类的实例作为构造器参数传递。

// 实现Runnable接口  
class MyRunnable implements Runnable {  
    @Override  
    public void run() {  
        // 在这里编写线程要执行的任务  
        System.out.println("线程运行中:" + Thread.currentThread().getName());  
    }  
}  
  
public class RunnableExample {  
    public static void main(String[] args) {  
        Thread t1 = new Thread(new MyRunnable());  
        t1.start(); // 启动线程  
    }  
}
4.3实现Callable接口

Callable接口是Java 5中引入的,与Runnable接口类似,但它可以返回一个结果,并且可以抛出异常。要实现Callable接口,你需要创建一个实现了该接口的类,并实现其call()方法。然而,你不能直接通过Callable接口来启动线程,因为Thread类并不接受Callable作为构造器参数。相反,你需要使用FutureTask类来包装Callable对象,FutureTask同时实现了FutureRunnable接口。然后,你可以像使用Runnable一样,通过Thread来执行FutureTask

// 实现Callable接口  
import java.util.concurrent.Callable;  
import java.util.concurrent.ExecutionException;  
import java.util.concurrent.FutureTask;  
  
class MyCallable implements Callable<String> {  
    @Override  
    public String call() throws Exception {  
        // 在这里编写线程要执行的任务  
        return "线程运行结果";  
    }  
}  
  
public class CallableExample {  
    public static void main(String[] args) {  
        MyCallable myCallable = new MyCallable();  
        FutureTask<String> futureTask = new FutureTask<>(myCallable);  
        Thread t1 = new Thread(futureTask);  
        t1.start(); // 启动线程  
  
        try {  
            // 获取Callable任务执行的结果  
            System.out.println("线程执行结果:" + futureTask.get());  
        } catch (InterruptedException | ExecutionException e) {  
            e.printStackTrace();  
        }  
    }  
}

Callable接口比Runnable接口提供了更强大的功能,特别是当你需要线程返回执行结果时。然而,这也意味着使用Callable会比使用Runnable稍微复杂一些,因为你需要处理Future对象以及可能抛出的异常。

标签:Runnable,Java,Thread,接口,Callable,线程,多线程,public
From: https://blog.csdn.net/m0_64821020/article/details/140160515

相关文章

  • java编译时出现错误[ERROR] 不再支持源选项 5。请使用 6 或更高版本。[ERROR] 不再支
    当我引入一个新项目在控制台输入命令mvn  clean install -U,报错出现原因是我们下载了多个java版本,我的电脑上就有1.8和11两个版本,此时只需在引入的pom文件中指定具体的版本即可<maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</mave......
  • Java实现简单的冒泡排序
    Java实现简单的冒泡排序核心思想:把相邻的两个数字两两比较,当一个数字大于右侧相邻的数字时,交换他们的位置,当一个数字和他右侧的数字小于或等于的时候,不交换。(小到大排序)例如有数组{3,1,5,7,4,2}第一次排序{3,1,5,7,4,2}//开始{1,3,5,7,4,2}//1和3互换{1,3,5,7,4,2......
  • 深入探索Java IO与NIO:差异与高性能网络编程的应用
    深入探索JavaIO与NIO:差异与高性能网络编程的应用一、引言在Java中,I/O(Input/Output)操作是应用程序与外部世界交互的基本方式。Java标准库提供了多种I/O模型,其中最常用的有传统的I/O(即阻塞I/O)和新引入的NIO(Non-blockingI/O,非阻塞I/O)。随着网络应用的日益复杂和性能要求的......
  • 基于Java+Vue的采购管理系统:采购过程合规高效(整套代码)
         前言:采购管理系统是一个综合性的管理平台,旨在提高采购过程的效率、透明度,并优化供应商管理。以下是对各个模块的详细解释:一、供应商准入供应商注册:供应商通过在线平台进行注册,填写基本信息和资质文件。资质审核:系统对供应商提交的资质文件进行自动或人工审核,确......
  • Java私有仓库Nexus搭建(喂奶式教程)
     1.为什么需要搭建私有仓库?1.有些公司都不提供外网给项目组人员,因此就不能使用maven访问远程的仓库地址,所以很有必要在局域网里找一台有外网权限的机器,搭建nexus私服,然后开发人员连到这台私服上,这样的话就可以通过这台搭建了nexus私服的电脑访问maven的远程仓库。而且自己......
  • Java流程控制
    一、顺序结构顺序结构是最简单的算法结构,它是任何一个算法都离不开的一种基本算法结构。二、选择结构if单选择结构(if)packagestruct;​importjava.util.Scanner;​publicclassDemo01{  publicstaticvoidmain(String[]args){    Scannerscann......
  • java使用Netty实现TCP收发消息的例子,多线程并且含断线自动重连
    需求:有一个TCP的服务,需要使用Netty开发一个TCP连接并收发消息的程序。要求多线程并且含断线自动重连能力。组织结构,使用JavaMaven编程方式功能还包含读取配置文件和log4j2写日志部分 完整代码:App.javapackagecom.LSpbxServer;importorg.slf4j.Logger;import......
  • java 事件回调的写法,使用回调接口方式
    java编写时,尤其是先用C#语言后转成java的,在编程时一定会遇到,java中没有委托事件的概念。那主类App.java类中实例了一个A对象,那A对象因为某种原因触发了一个事件,想回调App.java中的一个函数,应该怎么写呢?在java中有多有方法来实现,这里讲下回调接口方式,我感觉这种方式比较好理解......
  • java第三十课 —— 面向对象练习题
    面向对象编程练习题第一题定义一个Person类{name,age,job},初始化Person对象数组,有3个person对象,并按照age从大到小进行排序,提示,使用冒泡排序。packagecom.hspedu.homework;importjava.util.SortedMap;publicclassHomework01{publicstaticvo......
  • 2024最新Java笔试题及答案,java高分面试指南
    一、mybatis:1、当实体类中的属性名和表中的字段名不一样,怎么办1、使用as关键字起别名​<sqlid="Base_Column_List"><!--数据库种表的字段as实体类属性-->uidasid,userNameasname,ageasage,emailasemail,create_timeascreateTime,update_timeas......