Java——线程池

一、认识线程池

1.1、什么是线程池?

线程池就是一个可以复用线程的技术。

1.2、不使用线程池的问题

用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

1.3、线程池的工作原理

二、创建线程池

JDK5.0起提供了代表线程池的接口:ExecutorService。

2.1、如何创建线程池对象?

方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

方式二:使用Executors(线程池的工具类)调用方法返回不同特点的线程池对象。

2.2、方式一:通过 ThreadPoolExecutor 创建线程池

2.2.1、介绍

1、什么时候开始创建临时线程?

新任务提交时发现核心线程都在忙,任务队列也满了,并且还可以创建临时线程,此时才会创建临时线程。

2、什么时候会拒绝新任务?

核心线程和临时线程都在忙,任务队列也满了,新的任务过来的时候才会开始拒绝任务。

3、任务拒接策略

2.2.2、示例

1、处理 Runnable 任务

ExecutorService的常用方法

import java.util.concurrent.*;

public class ExecutorServiceDemo1 {
    public static void main(String[] args) {
        // 目标:创建线程池对象来使用。
        // 1、使用线程池的实现类ThreadPoolExecutor声明七个参数来创建线程池对象。
        ExecutorService pool = new ThreadPoolExecutor(3, 5,
                10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
               Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

        // 2、使用线程池处理任务!看会不会复用线程?
        Runnable target = new MyRunnable();
        pool.execute(target); // 提交第1个任务 创建第1个线程 自动启动线程处理这个任务
        pool.execute(target); // 提交第2个任务 创建第2个线程 自动启动线程处理这个任务
        pool.execute(target); // 提交第2个任务 创建第3个线程 自动启动线程处理这个任务
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);
        pool.execute(target); // 到了临时线程的创建时机了
        pool.execute(target); // 到了临时线程的创建时机了
        pool.execute(target); // 到了任务拒绝策略了,忙不过来

        // 3、关闭线程池 :一般不关闭线程池。
//        pool.shutdown(); // 等所有任务执行完毕后再关闭线程池!
//        pool.shutdownNow(); // 立即关闭,不管任务是否执行完毕!
    }
}
// 1、定义一个线程任务类实现Runnable接口
public class MyRunnable implements Runnable {
    // 2、重写run方法,设置线程任务
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "输出:" + i);
            try {
                Thread.sleep(Integer.MAX_VALUE);
            } catch (Exception e) {
               e.printStackTrace();
            }
        }
    }
}
2、处理Callable任务

ExecutorService的常用方法

import java.util.concurrent.*;

public class ExecutorServiceDemo2 {
    public static void main(String[] args) {
        // 目标:创建线程池对象来使用。
        // 1、使用线程池的实现类ThreadPoolExecutor声明七个参数来创建线程池对象。
        ExecutorService pool = new ThreadPoolExecutor(3, 5,
                10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),
               Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

        // 2、使用线程池处理Callable任务!
        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));
        Future<String> f3 = pool.submit(new MyCallable(300));
        Future<String> f4 = pool.submit(new MyCallable(400));

        try {
            System.out.println(f1.get());
            System.out.println(f2.get());
            System.out.println(f3.get());
            System.out.println(f4.get());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
import java.util.concurrent.Callable;

// 1、定义一个实现类实现Callable接口
public class MyCallable implements Callable<String> {
    private int n;
    public MyCallable(int n) {
        this.n = n;
    }
    // 2、实现call方法,定义线程执行体
    public String call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += i;
        }
        return Thread.currentThread().getName() +"计算1-" + n + "的和是:"  + sum;
    }
}

2.3、方式二:通过Executors 创建线程池(不推荐)

2.3.1、介绍

注意:

这些方法的底层,都是通过线程池的实现类ThreadPoolExecutor创建的线程池对象。
Executors使用可能存在的陷阱。大型并发系统环境中使用Executors如果不注意可能会出现系统风险。

2.3.1、示例

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

public class ExecutorsDemo3 {
    public static void main(String[] args) {
        // 目标:通过线程池工具类:Executors,调用其静态方法直接得到线程池
        ExecutorService pool = Executors.newFixedThreadPool(3);

        Future<String> f1 = pool.submit(new MyCallable(100));
        Future<String> f2 = pool.submit(new MyCallable(200));
        Future<String> f3 = pool.submit(new MyCallable(300));
        Future<String> f4 = pool.submit(new MyCallable(400));

        try {
            System.out.println(f1.get());
            System.out.println(f2.get());
            System.out.println(f3.get());
            System.out.println(f4.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值