线程池

Executor

在这里插入图片描述

  • 只有一个execute方法,入参是一个Runnable 线程
  • 实现线程的创建和运行分离
  • 是个接口,可以各种实现

ExecutorService

在这里插入图片描述

  • ExecutorService继承了Executor
  • submit 方法,入参是Callable 出参是 Future
  • executorService.execute 立马执行
  • executorService.submit 交给线程池来执行

Callable

  • 创建一个Callable方法,重写call方法(写自己的业务逻辑)
  • 创建一个ExecutorService
  • 调用submit方法
  • 用future接受出参
  • Future.get()方法,阻塞方法,直到线程执行结束
  • executorService.shutdown()关闭服务
public class thread_pool_01_callable {

    public static void main(String[] args) {

        Callable callable =  new Callable() {
            @Override
            public Object call() throws Exception {
                try{
                    Thread.sleep(1000);
                }catch (Exception e){

                }
                return 99;
            }
        };
        ExecutorService executorService = Executors.newCachedThreadPool();
        try{
            Future submit = executorService.submit(callable);
            System.out.println(submit.get());
        }catch (Exception e){

        }finally {
            executorService.shutdown(); //关闭
        }
    }
}
  • java8写法
public class thread_pool_02_callable {

    public static void main(String[] args) {


        ExecutorService executorService = Executors.newCachedThreadPool();
        try{
            Future submit = executorService.submit(()->{
                try{
                    Thread.sleep(1000);
                }catch (Exception e){

                }
                return 99;
            });
            System.out.println(submit.get());
        }catch (Exception e){

        }finally {
            executorService.shutdown(); //关闭
        }
    }
}

在这里插入图片描述

Callable 和 Future接口的区别

1 Callable规定的方法是call(),而Runnable规定的方法是run().
2 Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
3 call()方法可抛出异常,而run()方法是不能抛出异常的。
4 运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。 它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
5 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
6 Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。

Future

  • future.get() 获取当前方法返回值(阻塞方法)
    在这里插入图片描述

FutureTask

  • FutureTask 是 callable 和 future 的组合
  • 既能异步实现又能有返回值
public class thread_pool_03_futuretask {

    public static void main(String[] args) {

        FutureTask futureTask = new FutureTask(()->{
            try{
                Thread.sleep(1000);
            }catch (Exception e){

            }
            return 999;
        });

        new Thread(futureTask).start();
        try{
            System.out.println(futureTask.get());
        }catch (Exception e){

        }
    }
}

ComplatetableFuture

  • 多线程执行完成,结果汇总合集
  • CompletableFuture.allOf(); 所有线程执行完成
  • CompletableFuture.anyOf(jd, tb, tm); 任意一线程执行完成
/**
 * @author: lianghengyu
 * @time: 2020-05-02
 * @desc: 分别调用三大网站, 获取三个网站奥迪的价格 汇总展示
 */
public class thread_pool_04_completablefuture {

    public static void main(String[] args) {

        long timeMillis = System.currentTimeMillis();
        CompletableFuture jd = CompletableFuture.supplyAsync(() ->priceOfJD());
        CompletableFuture tb = CompletableFuture.supplyAsync(() ->priceOfTB());
        CompletableFuture tm = CompletableFuture.supplyAsync(() ->priceOfTM());

        CompletableFuture.allOf(jd, tb, tm);

        try{
            System.err.println("jd  "+jd.get());
            System.err.println("tm  "+tm.get());
            System.err.println("tb  "+tb.get());
        }catch (Exception e){

        }
        System.out.println(System.currentTimeMillis()-timeMillis);

    }

    private static double priceOfTM() {
        delay();
        return 1.00;
    }

    private static double priceOfTB() {
        delay();
        return 2.00;
    }

    private static double priceOfJD() {
        delay();
        return 3.00;
    }

    private static void delay() {
        int time = new Random().nextInt(500);
        try {
            TimeUnit.MILLISECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("After %s sleep!\n", time);
    }
}

ThreadPool

  • 线程集合
  • 任务队列
  • 核心线程和最大线程数关系
    • 当线程来的时候,先去拿核心线程
    • 核心线程用完了,再来线程进任务队列等待
    • 当任务队列满了,才增加线程池中的数量,执行任务
public class thread_pool_05_threadpool {

    static class Task implements Runnable {
        private int i;

        public Task(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Task " + i);
            try {
                System.in.read();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public String toString() {
            return "Task{" +
                    "i=" + i +
                    '}';
        }
    }


    public static void main(String[] args) {

        ThreadPoolExecutor pool = new ThreadPoolExecutor(2, 4, 500, TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 3; i++) {
            pool.execute(new Task(i));
        }
    }
}
七大参数
  • corePoolSize 核心线程数
  • maximumPoolSize 最大线程数
  • keepAliveTime 最大线程数保持时间(到期删除)
  • TimeUnit 时间类型
  • BlockingQueue workQueue 线程队列类型
  • ThreadFactory threadFactory 线程工厂
  • RejectedExecutionHandler handler 拒绝策略(当任务队列满了,没有空闲线程了)
    在这里插入图片描述
四种拒绝策略:
  • AbortPolicy 直接抛异常
  • DiscardPolicy 扔掉,不抛异常
  • DiscardOldestPolicy 扔掉队列中最久的线程
  • CallerEunsPolicy 调用者处理任务(谁调用,谁来执行他)
更改这个来进行测试

在这里插入图片描述

public class T05_00_HelloThreadPool {

    static class Task implements Runnable {
        private int i;

        public Task(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName() + " Task " + i);
            try {
                System.in.read();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public String toString() {
            return "Task{" +
                    "i=" + i +
                    '}';
        }
    }

    public static void main(String[] args) {
        ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4,
                60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<Runnable>(4),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

        for (int i = 0; i < 8; i++) {
            tpe.execute(new Task(i));
        }

        System.out.println(tpe.getQueue());

        tpe.execute(new Task(100));

        System.out.println(tpe.getQueue());

        tpe.shutdown();
    }
}
delphi线程池单元文件uThreadPool.pas,用法如下 type TRecvCommDataWorkItem=class(TWorkItem) public // updatetime,addtime:TDateTime; // orderid,ordertype,urljson,loadcount,savepath:string; url,Filename:string; total,order:Integer; _orderid:string; failedcount:Integer; IFCoverFile:Boolean; // 线程处理请求时触发的事件 procedure DealwithCommRecvData(Sender: TThreadsPool; WorkItem: TWorkItem; aThread: TProcessorThread); // 线程初始化时触发的事件 procedure TProcessorThreadInitializing(Sender: TThreadsPool; aThread:TProcessorThread); // 线程结束时触发的事件 procedure TProcessorThreadFinalizing(Sender: TThreadsPool; aThread:TProcessorThread); //任务队列空时触发的事件 procedure TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); end; 先声明一个类 然后用法 FThreadPool := TThreadsPool.Create(nil); // 创建线程池 FThreadPool.ThreadsMin := 10; // 初始工作线程数 FThreadPool.ThreadsMax := 100; // 最大允许工作线程数 AWorkItem := TRecvCommDataWorkItem.Create; ISAllOverLoad:=False; AWorkItem.url:=urljson; AWorkItem.order:=i; AWorkItem.total:=JA.Count; AWorkItem.Filename:=savefilepath; AWorkItem._orderid:=orderid; AWorkItem.IFCoverFile:=IFCoverFile; FThreadPool.AddRequest(AWorkItem,True); // 向线程池分配一个任务 FThreadPool.OnProcessRequest := AWorkItem.DealwithCommRecvData; FThreadPool.OnThreadInitializing := AWorkItem.TProcessorThreadInitializing; FThreadPool.OnThreadFinalizing := AWorkItem.TProcessorThreadFinalizing; FThreadPool.OnQueueEmpty := AWorkItem.TQueueEmpty; 仔细看下线程池单元的函数说明轻松搞定。 procedure TRecvCommDataWorkItem.TQueueEmpty(Sender: TThreadsPool; EmptyKind: TEmptyKind); begin if EmptyKind=ekProcessingFinished then begin try if Assigned(geturl) then //存在的bug 如果下载文件存在的不行 begin //Sleep(200); //激活线程可能会发生在 休眠之前!! ISAl
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值