Java中的多线程(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36209121/article/details/77101313

前言

前面我们已经介绍了两种多线程的实现方式Java中的多线程(1), 现在接着总结第3种实现方式.

当我们需要获得线程中的返回值的时候可以使用下面的方式来实现.


二, 能获得返回值的多线程

如果要获得线程处理的返回值需要用到Callable接口, 使用ExecutorService来管理, 返回值由Future对象来处理.

  • 创建task类, 实现Callable接口, 重写run方法;
  • 创建线程池, 获得ExecutorService对象;
  • 将我们创建的线程对象作为参数传入到submit方法中;
  • 获得返回值Future对象;

代码如下

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

public class ThreadMain02 {

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        try {
            for(int i=0;i<5;i++) {
                Future<String> future = executorService.submit(new ThreadCallable01());
                System.out.println(future.get().toString());
            }
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            executorService.shutdown();
        }
    }
}

class ThreadCallable01 implements Callable<String> {
    private Integer total;

    @Override
    public String call() throws Exception {
        return Thread.currentThread().getName()+" -- is running";
    }
}

获取线程中的返回值

在我们获取线程中的返回值的时候, 可以自己创建一个Future的list来保存获得返回值的集合, 但是当有线程没有获得返回值的时候会产生线程的阻塞, 导致后面完成的任务不能及时得到结果, 直到该线程得到返回结果位置.


为了解决这种情况, 可以使用ExecutorCompletionService来获得获结果集;
运行下面的代码:

package com.test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadMain03 {

    public static void main(String[] args) {
        int threads = 10;
        ExecutorService es = Executors.newFixedThreadPool(threads);
        ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(es);
        try {
            for(int i=0;i<5;i++) {
                completionService.submit(new TaskCallable03((threads-i),i));
            }

            for(int i=0;i<5;i++) {
                System.out.println("i="+i+" -- "+completionService.take().get());
            }
        }catch(Exception e) {
            e.printStackTrace();
        }finally {
            es.shutdown();
        }
    }
}

class TaskCallable03 implements Callable<String> {
    private int time;
    private int num;

    public TaskCallable03(int time, int num) {
        this.time=time;
        this.num = num;
    }

    @Override
    public String call() throws Exception {
        Thread.sleep(time);
        return Thread.currentThread().getName()+" -- is running" + " -- num="+num;
    }
}

返回的结果

i=0 -- pool-1-thread-1 -- is running -- num=0
i=1 -- pool-1-thread-5 -- is running -- num=4
i=2 -- pool-1-thread-4 -- is running -- num=3
i=3 -- pool-1-thread-3 -- is running -- num=2
i=4 -- pool-1-thread-2 -- is running -- num=1

从上面的运行结果, 并且结合ExecutorCompletionService的代码:
ExecutorCompletionService中有一个BlockingQueue队列, 实现的是LinkedBlockingQueue链表结构的队列,
先执行完的, 先放到ExecutorCompletionService对象的结果集中, 这样就避免了前面的结构没有执行完成导致的阻塞效应.


参考了许多大牛的博客, 如有不当地方, 欢迎告知, 谢谢.

猜你喜欢

转载自blog.csdn.net/qq_36209121/article/details/77101313
今日推荐