Java多线程之Worker Thread模式

Java多线程之Worker Thread模式

什么是Worker Thread模式

Worker Thread模式是一种有效的多线程设计模式,用于在并发环境中处理多个请求,提高应用的响应性能和并发能力。

在Worker Thread模式中,主线程负责接收任务,把任务交给线程池中的工作线程去处理,主线程不断地接收任务,工作线程不断地从队列中取出任务并执行,一个任务只由一个工作线程处理,处理完毕后继续去取下一个任务。

如何使用Worker Thread模式

在Java中,使用Worker Thread模式一般需要按照以下步骤来实现:

  1. 创建工作任务类:定义一个类,实现Runnable接口,实现工作线程需要执行的任务逻辑。

java
public class WorkTask implements Runnable {
@Override
public void run() {
// 执行任务逻辑
}
}

  1. 创建线程池:调用ThreadPoolExecutor构造函数创建线程池,设置核心线程数、最大线程数、线程存活时间和任务队列等参数。

java
ExecutorService executor = new ThreadPoolExecutor(
corePoolSize, // 设置核心线程数
maximumPoolSize, // 设置最大线程数
keepAliveTime, TimeUnit.SECONDS, // 设置线程存活时间
new ArrayBlockingQueue<Runnable>(queueSize) // 设置任务队列
);

  1. 提交任务:将任务提交给线程池执行。

java
executor.submit(new WorkTask());

  1. 关闭线程池:任务执行完毕后需要关闭线程池,释放资源。

java
executor.shutdown();

示例说明

示例1:并发计算1到100的和

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class SumTask implements Runnable {
    private int start;
    private int end;
    private int result;

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

    public int getResult() {
        return result;
    }

    @Override
    public void run() {
        for (int i = start; i <= end; i++) {
            result += i;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        int totalCount = 0;
        for (int i = 1; i <= 10; i++) {
            int start = totalCount + 1;
            int end = totalCount + 10;
            executor.submit(new SumTask(start, end));
            totalCount += 10;
        }
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.HOURS);
        int sum = 0;
        while (!executor.isTerminated()) {
            // do nothing
        }
        for (int i = 1; i <= 10; i++) {
            SumTask task = (SumTask) executor.submit(new SumTask(i, i));
            sum += task.getResult();
        }
        System.out.println("sum is: " + sum);
    }
}

上面的代码实现了并发计算1到100的和的功能,大致过程如下:

  1. 定义了一个SumTask类实现了Runnable接口,SumTask类的构造函数接收起始数值和结束数值,在run()方法中完成计算累加的操作。
  2. 使用ExecutorService的newFixedThreadPool()方法创建了一个包含10个线程的线程池,每个线程负责从1到10、11到20、……、91到100计算和值。
  3. 执行完所有任务之后,调用awaitTermination()方法等待所有任务执行完毕。
  4. 计算各个线程的累加和,得到最终结果。

示例2:下载多个文件

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class DownloadTask implements Runnable {
    private String url;
    private String filename;

    public DownloadTask(String url, String filename) {
        this.url = url;
        this.filename = filename;
    }

    @Override
    public void run() {
        try (BufferedInputStream in = new BufferedInputStream(new URL(url).openStream());
             FileOutputStream fileOutputStream = new FileOutputStream(filename)) {
            byte[] dataBuffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
                fileOutputStream.write(dataBuffer, 0, bytesRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        String[] urls = {
                "https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js",
                "https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js",
                "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js",
                "https://cdn.jsdelivr.net/npm/react@17.0.2/umd/react.production.min.js"
        };
        for (String url : urls) {
            executor.submit(new DownloadTask(url, url.substring(url.lastIndexOf("/") + 1)));
        }
        executor.shutdown();
        executor.awaitTermination(1, TimeUnit.MINUTES);
    }
}

上面的代码实现了下载多个文件的任务,大致过程如下:

  1. 定义了一个DownloadTask类实现了Runnable接口,DownloadTask类的构造函数接收要下载的URL和文件名,在run()方法中完成下载的操作。
  2. 使用ExecutorService的newFixedThreadPool()方法创建了一个包含10个线程的线程池,每个线程负责下载不同的文件。
  3. 执行完所有任务之后,调用awaitTermination()方法等待所有任务执行完毕。

以上就是关于Java多线程之Worker Thread模式的完整攻略,希望能够帮助读者更好地理解这一设计模式及其相关应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java多线程之Worker Thread模式 - Python技术站

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

相关文章

  • Java网络编程UDP实现多线程在线聊天

    Java网络编程UDP实现多线程在线聊天 简介 在Java网络编程中,UDP是经常被使用的协议之一。它能够实现高效的数据传输,适用于区分实时性高和低的两类应用场景。本文将分享如何通过Java网络编程中的UDP协议来实现在线聊天,其中还涉及到了多线程的实现。 环境准备 Java JDK Eclipse或者IntelliJ IDEA等IDE 一台或多台计算机 开…

    多线程 2023年5月16日
    00
  • 关于python并发编程中的协程

    关于Python并发编程中的协程,以下是一个完整攻略: 什么是协程 协程是一种轻量级的线程,它可以在同一进程内同时运行多个协程,并且在协程中可以通过“挂起”和“恢复”操作来实现非阻塞式的并发编程。 协程的实现 在Python3.5版本以后,Python引入了asyncio关键字来对协程实现进行支持。 使用async、await关键字定义协程函数,并且使用as…

    多线程 2023年5月17日
    00
  • 详解Java中的线程模型与线程调度

    详解Java中的线程模型与线程调度 线程模型 在Java中,线程的实现是基于OS的线程(Native Thread)实现的。每个Java线程对应了一个OS线程。 线程模型主要由执行线程和阻塞线程两部分组成。执行线程就是正在执行的线程,阻塞线程就是等待某些事件或条件才能执行的线程。 当线程遇到IO或者锁时,线程进入阻塞状态,被加入到对应的阻塞队列中。等待IO或…

    多线程 2023年5月17日
    00
  • python并发编程之多进程、多线程、异步和协程详解

    Python并发编程之多进程、多线程、异步和协程详解 前言 在Python3中,并发编程是非常重要的一部分,开发者可以使用多种方式来实现并发编程,比如多进程、多线程、异步和协程等。这篇文章将详细介绍这几种方式的用法,及其适用场景。 多进程 多进程是指在操作系统上同时运行多个进程,每个进程都是独立的执行流,各自拥有自己的内存空间和资源。在Python中,可以使…

    多线程 2023年5月16日
    00
  • java多线程CyclicBarrier的使用案例,让线程起步走

    下面开始为大家详细讲解Java多线程CyclicBarrier的使用案例。 什么是CyclicBarrier? CyclicBarrier是Java多线程中的一个构造器,它可以协调多线程间的运行,实现多个线程阻塞至某个状态之后再全部同时执行。可以说CyclicBarrier是控制多线程执行时序的一种工具。 CyclicBarrier的使用场景 CyclicB…

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

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

    多线程 2023年5月17日
    00
  • 高并发下Redis如何保持数据一致性(避免读后写)

    在高并发下,Redis的数据一致性是一个重要的问题,特别是在读后写的情况下。为了保持数据一致性,我们可以采取以下措施: 1. 使用Redis的事务 Redis的事务可以将多个命令进行原子化批量执行,这可以避免读后写的问题。具体来说,我们可以将读和写操作都放在一个事务里面,这样就能确保只有这个事务内的操作可以生效。 例如,我们可以使用以下代码: MULTI G…

    多线程 2023年5月17日
    00
  • python并发场景锁的使用方法

    针对“python并发场景锁的使用方法”的完整攻略,我给您提供以下四个部分的内容: 一、什么是并发相关的锁? 并发相关的锁,是指一种机制,用于在多个线程或进程中,对一件共享资源进行访问时的互斥保护。在并发场景下,通常使用这种锁来避免竞态条件(race condition)和死锁(deadlock)等问题。Python的标准库提供了多个并发相关的锁,主要包括 …

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