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多线程 原子操作类详细 什么是原子操作? 在计算机科学中,原子操作是指不可被进一步分割的操作。即使在并行的情况下执行,原子操作也会被看作是单个操作,不会被其他操作中断。在多线程编程中,对共享数据的修改必须是原子操作,否则就会出现竞态条件(Race Condition)的问题。 Java多线程中的原子操作 Java并发包中提供了一系列的原子操作类,包括…

    多线程 2023年5月16日
    00
  • 分析MySQL并发下的问题及解决方法

    分析MySQL并发下的问题及解决方法 在高并发场景下,MySQL的性能表现可能会因为死锁、慢查询等问题而受到影响。因此,在开发应用程序时,需要注意这些问题,避免性能瓶颈或者线程阻塞。本文将讨论MySQL并发下的问题及解决方法。 分析MySQL并发问题 死锁 死锁是指两个或以上的事务在相互等待对方释放锁资源时发生的问题。在MySQL中,如果同时有多个事务修改同…

    多线程 2023年5月16日
    00
  • Java并发 CompletableFuture异步编程的实现

    Java并发 CompletableFuture是一种强大的异步编程工具,它可以让我们轻松地编写高效的并发代码。在本文中,我们将探讨如何使用CompletableFuture,以及如何从中获益。 什么是CompletableFuture CompletableFuture是Java 8引入的一种并发编程工具。它是一种Future的扩展,它允许我们编写异步代码…

    多线程 2023年5月16日
    00
  • IIS Web服务器支持高并发设置方法详解

    IIS Web服务器支持高并发设置方法详解 在应对高并发场景下,IIS Web服务器的配置是至关重要的。本文将介绍如何通过设置来提高IIS的并发处理能力。 1. 修改IIS属性设置 第一步是修改IIS属性设置,以提高服务器并发处理能力。可以按以下步骤操作: 在控制面板中找到“管理工具”,然后点击“Internet 信息服务(IIS)管理器”进入IIS配置界面…

    多线程 2023年5月16日
    00
  • Java并发程序入门介绍

    Java并发程序入门介绍攻略 简介 Java并发编程是指在多线程环境下,多个线程之间相互合作、协同工作的编程模型。Java并发编程常常被采用于提高程序运行效率、提升程序响应速度以及提高程序质量等方面。本篇文章将简单介绍Java并发编程的基本知识,包括Java并发编程的常见术语、Java并发编程的核心知识点以及Java并发编程的示例等。 Java并发编程常见术…

    多线程 2023年5月16日
    00
  • PHP开发中解决并发问题的几种实现方法分析

    PHP开发中解决并发问题的几种实现方法分析 在 PHP 开发中,进行并发处理是非常常见的需求,比如在电商网站中,同一时间可能会有很多用户在同时进行下单、支付等操作。为了保证用户体验和数据的正确性,我们需要对并发问题进行处理。本篇文章将介绍几种常见的 PHP 并发问题解决方案。 方案一:使用锁机制 在 PHP 中,可以通过使用锁机制来解决并发问题。锁机制可以控…

    多线程 2023年5月16日
    00
  • 新手了解java 多线程基础知识

    以下是“新手了解Java多线程基础知识”的完整攻略: 了解Java多线程 一、基础概念 在开始探讨Java多线程之前,需要了解一些基础概念: 1. 线程 线程是操作系统调度执行的最小单元,是进程中的一个执行流程,可以理解为程序执行的一条执行路径。 2. 多线程 允许在一个程序中同时运行多个线程,每个线程执行不同的任务,从而提高程序的性能。Java中可以使用T…

    多线程 2023年5月17日
    00
  • C++11 并发指南之多线程初探

    C++11 并发指南之多线程初探 什么是多线程 多线程是指在一个进程中运行的多个不同执行流程,每个执行流程叫做一个线程。多线程可以使程序并行执行,提高程序效率。 为什么要使用多线程 在单线程程序中,程序按照顺序执行,如果程序中出现了耗时的操作,程序就会变得非常慢。使用多线程可以使程序中的耗时操作在不同的线程中执行,从而提高程序的执行效率。另外,多线程也可以使…

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