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

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对象以及可能抛出的异常。

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值