文档章节

Java并发编程高级篇(一):使用线程池执行器

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2017/02/28 14:50
字数 801
阅读 53
收藏 0

使用执行器框架(Executor Framework)的第一步是创建执行器ThreadPoolExecutor对象。我们可以使用ThreadPoolExecutor提供的四个构造函数,或者使用Executors工厂方法来创建线程执行器。一旦有了执行器,我们就可以把Runnable或Callable对象发送给它去执行了。

接下来我们使用执行器来实现一个能够处理客户端请求的服务器。

首先我们创建一个任务执行线程,这个线程用来模拟处理客户端的请求任务,它首先打印线程创建和启动时间,然后随机休眠一段时间用来模拟任务处理过程,最后打印任务结束时间。

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 任务执行类
 * Created by hadoop on 15/12/9.
 */
public class Task implements Runnable{
    private String name;
    private Date initDate;

    public Task(String name) {
        this.name = name;
        this.initDate = new Date();
    }

    /**
     * 任务过程
     * 1. 打印任务创建时间
     * 2. 打印任务开始时间
     * 3. 任务随机休眠一段时间
     * 4. 打印任务结束时间
     */
    @Override
    public void run() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        System.out.printf("%s: Task %s: Created on: %s\n",
                Thread.currentThread().getName(), name, format.format(initDate));
        System.out.printf("%s: Task %s: Started on: %s\n",
                Thread.currentThread().getName(), name, format.format(new Date()));

        long duration = (long)(Math.random() * 10);
        System.out.printf("%s: Task %s: Do something duration %d Seconds\n",
                Thread.currentThread().getName(), name, duration);
        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.printf("%s: Task %s: Finished on: %s\n",
                Thread.currentThread().getName(), name, format.format(new Date()));
    }
}

接下来我们创建服务端Server类,用来模拟接受客户端的请求,然后启动任务线程来处理请求,在这个类中,我们是用来线程处理器ThreadPoolExecutor。在这里我们使用了Executors.newCachedThreadPool()线程执行器工厂来创建线程执行器,这个方法会返回一个ExecutorService类型的对象,因此需要将它的类型转换为ThreadPoolExecutor类型。

如果需要执行任务,那么线程池执行器就会创建一个新的线程来执行这个任务,如果任务执行完毕,线程池会回收线程,当有新的任务进来的时候,将会从线程池中获取线程来执行这个任务。当然如果一次发送过多的任务给线程执行器,那么将会造成很高的系统负载。

import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 任务调度类
 * 1. 启动一个线程池:(ThreadPoolExecutor) Executors.newCachedThreadPool();
 * 2. 接受任务并加入到线程池中
 * 3. 所有任务之行结束后关闭线程池
 * Created by hadoop on 15/12/9.
 */
public class Server {
    ThreadPoolExecutor executor;

    public Server() {
        executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
    }

    /**
     * 执行任务并打印当前线程池状态
     * @param task 任务
     */
    public void execute(Task task) {
        System.out.println("Server: A new task has arrived.\n");
        executor.execute(task);
        //返回线程池中的线程数
        System.out.printf("Server: Pool Size: %d\n", executor.getPoolSize());
        //返回线程池中正在运行的线程数
        System.out.printf("Server: Active Count: %d\n", executor.getActiveCount());
        //返回线程池中已经完成的任务数
        System.out.printf("Server: Completed Task: %d\n", executor.getCompletedTaskCount());
    }

    public void endServer() {
        executor.shutdown();
    }
}

最后创建主类Main,并运行程序。

public class Main {
    /**
     * 创建10个任务并发送到线程池中
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        Server server = new Server();
        for (int i = 0; i < 10; i++) {
            Task task = new Task("Task" + i);
            server.execute(task);
            Thread.sleep(1000);
        }
        server.endServer();
    }
}

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 22
博文 91
码字总数 83019
作品 0
西城
程序员
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
JAVA多线程和并发基础面试问答

原文链接 译文连接 作者:Pankaj 译者:郑旭东 校对:方腾飞 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢...

雷神雨石
2014/07/19
0
2
JAVA多线程和并发基础面试问答

多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,但是你仍然应该牢固的掌握Java多线程基础知识来对应日后碰到的问题。(校对注:...

LCZ777
2014/05/26
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

清风傲剑
2014/12/06
0
0
JAVA多线程和并发基础面试问答

Java多线程面试问题 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一...

hanzhankang
2014/01/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

@SpringBootApplication 注解

@SpringBootApplication注解是一个组合注解,包含以下注解 @Target(ElementType.TYPE) 注解的作用目标 @Retention(RetentionPolicy.RUNTIME) Reteniton的作用是定义被它所注解的注解保留多久,...

java.刘
33分钟前
0
0
sentinel自定义DataSource实战

序 本文主要研究一下如何自定义sentinel的DataSource,这里以jdbc为例。 maven <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sen......

go4it
49分钟前
1
0
xgboost/gbdt在调参时为什么树的深度很少就能达到很高的精度?

问题: 用xgboost/gbdt在在调参的时候把树的最大深度调成6就有很高的精度了。但是用DecisionTree/RandomForest的时候需要把树的深度调到15或更高。用RandomForest所需要的树的深度和Decisio...

tantexian
50分钟前
0
0
php-fpm的pool - 慢执行日志 - 进程管理 - open_basedir

php-fpm的pool : 为避免多站点使用同一个pool时因一个站点故障导致php资源耗尽,牵连使用同一个pool的其他站点的正常工作,可对每一个站点设置独立pool。 增加pool: 1.编辑php-fpm配置文件...

ZHENG-JY
今天
0
0
Linux之ssh服务默认端口修改

导读 SSH是标准的网络协议,可用于大多数UNIX操作系统,能够实现字符界面的远程登录管理,它默认使用22号端口,采用密文的形式在网络中传输数据,相对于通过明文传输的Telnet,具有更高的安全...

问题终结者
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部