Java 线程对比(Thread,Runnable,Callable)实例详解

Java 线程对比(Thread,Runnable,Callable)实例详解

介绍

Java线程(Thread)是Java程序中运行的最小单元,是实现并发编程的基础。在Java中,创建线程一般有三种方式:继承Thread类、实现Runnable接口和实现Callable接口。本文将对这三种方式进行详细比较,并提供示例说明。

Thread类

继承Thread类是Java创建线程最原始的方式。这种方式需要重写Thread类的run方法,在run方法中编写线程要执行的代码。示例代码如下:

public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程要执行的代码
    }
}

// 创建线程
MyThread thread = new MyThread();
// 启动线程
thread.start();

这种方式简单粗暴,但实现起来较为繁琐,因为Java只允许单继承,如果要扩展其他类,则不能使用此方式。

Runnable接口

实现Runnable接口是Java创建线程的常见方式,由于Java中可以实现多个接口,因此这种方式具有较高的灵活性。Runnable接口只有一个run方法,需要在线程中重写run方法,在run方法中编写线程要执行的代码。示例代码如下:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // 线程要执行的代码
    }
}

// 创建线程
Thread thread = new Thread(new MyRunnable());
// 启动线程
thread.start();

可以看出,与继承Thread类相比,实现Runnable接口更具有可扩展性。此外,使用Runnable方式还可以将线程的代码和线程独立开来,便于重用。

Callable接口

在JDK5.0之后,Java引入了Callable接口,它和Runnable接口类似,也是一个可以在线程中执行的任务,但是它可以返回执行结果。Callable接口的实现类必须通过FutureTask包装器线程才能执行。示例代码如下:

public class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        // 线程要执行的代码
        return 线程执行结果;
    }
}

// 创建线程
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallable());
Thread thread = new Thread(futureTask);
// 启动线程
thread.start();

// 获取线程执行结果
Integer result = futureTask.get();

和Runnable接口相比,Callable接口可以返回线程执行结果,适用于需要返回结果的线程。

示例说明

示例一:使用Runnable接口实现多线程下载文件

public class DownloadFile implements Runnable {
    private String url;
    private String fileName;
    private int startIndex;
    private int endIndex;

    public DownloadFile(String url, String fileName, int startIndex, int endIndex) {
        this.url = url;
        this.fileName = fileName;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }

    @Override
    public void run() {
        try {
            URL url = new URL(this.url);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Range", "bytes=" + this.startIndex + "-" + this.endIndex);

            InputStream inStream = conn.getInputStream();
            RandomAccessFile file = new RandomAccessFile(this.fileName, "rw");
            file.seek(this.startIndex);

            byte[] buffer = new byte[1024];
            int length = 0;
            while ((length = inStream.read(buffer)) != -1) {
                file.write(buffer, 0, length);
            }

            file.close();
            inStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        String url = "https://example.com/file.zip";
        String fileName = "file.zip";
        int threadCount = 4;

        try {
            URL fileUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) fileUrl.openConnection();
            int fileSize = conn.getContentLength();
            conn.disconnect();

            int blockSize = fileSize / threadCount;

            for (int i = 0; i < threadCount; i++) {
                int startIndex = i * blockSize;
                int endIndex = (i + 1) * blockSize - 1;
                if (i == threadCount - 1) {
                    endIndex = fileSize - 1;
                }

                new Thread(new DownloadFile(url, fileName, startIndex, endIndex)).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

本示例中,使用Runnable接口实现了多线程下载文件。通过获取文件大小,将文件分成多块,通过多个线程同时下载,从而提高了下载速度。

示例二:使用Callable接口实现多线程计算

public class Calculator implements Callable<Integer> {
    private int start;
    private int end;

    public Calculator(int start, int end) {
        this.start = start;
        this.end = end;
    }

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

public class Main {
    public static void main(String[] args) {
        int start = 1;
        int end = 100;
        int threadCount = 4;
        int sum = 0;

        try {
            ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
            List<Future<Integer>> futures = new ArrayList<>();

            int blockSize = (end - start + 1) / threadCount;
            for (int i = 0; i < threadCount; i++) {
                int startIndex = start + i * blockSize;
                int endIndex = startIndex + blockSize - 1;
                if (i == threadCount - 1) {
                    endIndex = end;
                }

                Callable<Integer> callable = new Calculator(startIndex, endIndex);
                Future<Integer> future = executorService.submit(callable);
                futures.add(future);
            }

            for (Future<Integer> future : futures) {
                sum += future.get();
            }

            executorService.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("1-100的和为:" + sum);
    }
}

本示例中,使用Callable接口实现了多线程计算1-100之间所有数的和。将任务拆分成多个子任务,通过线程池执行,最终将子任务的结果合并,从而提高了计算速度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 线程对比(Thread,Runnable,Callable)实例详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 实例分析Java单线程与多线程

    实例分析Java单线程与多线程 Java线程(Thread)是程序执行的最小单元,可以在单线程和多线程两种模型中运行。单线程模型指该程序只有一个线程,而多线程模型则允许多个线程同时运行。在实际编程中,面对复杂的任务和高并发情况,多线程逐渐变得不可避免。因此,本文将详细讲解实例分析Java单线程与多线程的完整攻略。 Java单线程模型 在Java单线程模型下,…

    多线程 2023年5月17日
    00
  • Java并发编程之ThreadLocal详解

    Java并发编程之ThreadLocal详解 什么是ThreadLocal? ThreadLocal 是 Java 中用于实现线程本地变量的机制,它提供了一种让每个线程独立管理变量的方式。也就是说,ThreadLocal 可以为每个线程创建一个单独的变量副本,各个线程之间互不干扰。这种机制在多线程编程中很常见,它可以解决多线程条件下数据共享和线程安全的问题。…

    多线程 2023年5月17日
    00
  • 并发数据库压力测试的shell脚本代码

    要进行并发数据库压力测试,可以使用ab(Apache Bench)工具。使用shell脚本代码可以简化测试过程,并且可以多次执行测试以获得可靠的结果。 以下是一个示例shell脚本,用于进行简单的并发数据库压力测试: #!/bin/bash # 设置测试参数 url="http://localhost:8080/api/users" co…

    多线程 2023年5月17日
    00
  • 带你快速搞定java多线程(3)

    当我们需要处理一些比较消耗时间的操作时,多线程可以提高程序的执行效率,因此实现多线程在Java编程中也显得尤为重要。本文将带你从多方面快速搞定Java多线程,实现多任务并发执行。 1. 创建线程的三种方式 在Java中,创建线程的方式有三种:继承Thread类、实现Runnable接口以及使用线程池。 1.1 继承Thread类 继承Thread类是最简单的…

    多线程 2023年5月17日
    00
  • C# List 并发丢数据问题原因及解决方案

    C# List 并发丢数据问题原因及解决方案 问题描述 在多线程环境下,使用C#的List时,会存在添加元素丢失、重复、越界等问题,导致程序出现异常或不可预料的结果。这是由于List本身并不是线程安全的集合类,多个线程同时对其进行写操作时,会导致竞争条件,从而出现数据异常。 原因分析 List是一个基于数组的集合类型,当多个线程同时对其进行写操作时,可能会导…

    多线程 2023年5月17日
    00
  • PHP高并发和大流量解决方案整理

    PHP高并发和大流量解决方案整理 在如今互联网时代,高并发和大流量是所有Web开发中必须要解决的问题。在PHP开发中,如何解决高并发和大流量成为了开发者不可避免地要面对的问题。本文将为大家介绍PHP高并发和大流量的解决方案。 1. 前端优化 1.1 页面压缩 通过GZIP压缩可以减少传输的数据量,从而提升网页加载速度。可以通过修改Apache或Nginx的配…

    多线程 2023年5月16日
    00
  • RocketMQ Broker实现高可用高并发的消息中转服务

    这里是 RocketMQ Broker 实现高可用高并发的消息中转服务的完整攻略: 1. 背景 RocketMQ 是阿里巴巴开源的分布式消息系统,目前在行业内使用非常广泛。在一个企业级应用程序中,系统的高可用性是至关重要的,这意味着您必须确保当出现硬件或软件故障时,系统将不会完全停止。为了实现高可用性,我们需要在消息中间件中引入 Broker 集群。 Roc…

    多线程 2023年5月17日
    00
  • C++可扩展性与多线程超详细精讲

    C++可扩展性与多线程超详细精讲 前言 C++语言是一门十分强大且广泛应用的编程语言,其可用于开发各种不同类型的应用程序。本篇文章主要讲解C++的可扩展性与多线程编程。 可扩展性 在软件开发中,可扩展性是指当需求增加时,我们能够轻松扩展应用程序。以下是几个重要的概念: 抽象类和纯虚函数 抽象类中含有至少一个纯虚函数,纯虚函数是一个虚函数,在函数原型后面使用 …

    多线程 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部