Java并发编程高级篇(一):使用线程池执行器
Java并发编程高级篇(一):使用线程池执行器
阿拉德大陆的魔法师 发表于9个月前
Java并发编程高级篇(一):使用线程池执行器
  • 发表于 9个月前
  • 阅读 24
  • 收藏 0
  • 点赞 0
  • 评论 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();
    }
}
标签: java 并发
共有 人打赏支持
粉丝 21
博文 91
码字总数 83019
×
阿拉德大陆的魔法师
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: