检测线程是否执行完成并获取线程Thread的返回值

1、使用executor.isTerminated()判断线程池中的线程是否执行完成

/**
 * @author chuan
 * @title: ThreadResultTest
 * @description: TODO(获取Thread的返回值)
 */
public class ThreadResultTest implements Runnable{
    /**
     * 在没有获取Thread的返回值之前,先判断一下线程是否执行完成
     */

    private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class);
    // 线程安全的List集合
    private static List<String> sycnList = Collections.synchronizedList(new ArrayList<String>());
    // 创建一个线程池
    private static ExecutorService executor = Executors.newFixedThreadPool(1);

    private int count = 0;

    public ThreadResultTest(int count) {
        this.count = count;
    }

    @Override
    public void run() {
        try {
            sycnList.add("add data into collection");
            Thread.currentThread().setName("Thread-Pool");
            int nextInt = new Random().nextInt(100);
            Thread.sleep(nextInt);
            logger.info("execute result : " + count);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("thread execute error info:{},{}",e.getMessage(),e);
        }
    }

    public static void main(String[] args) throws Exception{
        for (int i = 0; i < 12; i++) {
            executor.execute(new ThreadResultTest(i));
        }
        System.out.println("execute info : 线程已添加到队列,正在执行中...");
        executor.shutdown();

        while (true) {
            Thread.sleep(1000);
            if(executor.isTerminated()) {
                System.out.printf("execute result : %s","所有的线程执行完毕!");
                break;
            }
        }
    }
}

输出结果:

2、通过while循环检测获取线程结果

/**
 * @author chuan
 * @title: ThreadResultTest
 * @description: TODO(获取Thread的返回值-while)
 */
public class ThreadResultTest implements Runnable{

    private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class);
    private Object result;
    public Object getResult() { return result;}

    @Override
    public void run() {
        try {
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ...");
            Thread.sleep(6000);
            // 模拟获取结果
            result = Integer.valueOf(new Random().nextInt(100));
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!");
        } catch (Exception e) {
            logger.error("thread execute error info:{},{}",e.getMessage(),e);
        }
    }

    public static void main(String[] args) throws Exception{
        ThreadResultTest callback = new ThreadResultTest();
        final String threadName = "Thread-Name";
        Thread thread = new Thread(callback,threadName);
        thread.start();
        // 循环检测线程的值
        while (true){
            if(callback.getResult()!=null){
                System.out.printf("execute result : %s",callback.getResult());
                break;
            }
            // 定时检测、提高一下性能
            Thread.sleep(1000);
            logger.info("execute check up info : " + callback.getResult());
        }
    }
}

输出结果:

3、通过wait、notify组合方式获取线程的值

/**
 * @author chuan
 * @title: ThreadResultTest
 * @description: TODO(获取Thread的返回值-wait和notify组合)
 */
public class ThreadResultTest implements Runnable{

    private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class);
    private Object result;
    public Object getResult() { return result;}

    @Override
    public void run() {
        try {
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ...");
            Thread.sleep(6000);
            // 模拟获取结果
            result = Integer.valueOf(new Random().nextInt(100));
            //唤醒wait的对象
            synchronized (this){
                this.notify();
            }
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!");
        } catch (Exception e) {
            logger.error("thread execute error info:{},{}",e.getMessage(),e);
        }
    }

    public static void main(String[] args) throws Exception {
        ThreadResultTest callback = new ThreadResultTest();
        final String threadName = "Thread-Name";
        Thread thread = new Thread(callback, threadName);
        thread.start();
        // 循环检测线程的值
        while (true) {
            if (callback.getResult() == null) {
                System.out.println("execute result : " + callback.getResult());
                // 如果获取的线程的值为null,则线程进入wait()状态,等待唤醒
                synchronized (callback) {
                    try {
                        callback.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (callback.getResult() != null) {
                logger.info("execute check up info : " + callback.getResult());
                break;
            }
        }
    }
}

输出结果:

4、使用LockSupport获取线程的值

/**
 * @author chuan
 * @title: ThreadResultTest
 * @description: TODO(获取Thread的返回值-LockSupport)
 */
public class ThreadResultTest implements Runnable{

    private static Logger logger = LoggerFactory.getLogger(ThreadResultTest.class);
    private Object result;
    public Object getResult() { return result;}
    Thread currRun;
    ThreadResultTest(Thread threadRun){
        this.currRun = threadRun;
    }

    @Override
    public void run() {
        try {
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ...");
            Thread.sleep(6000);
            // 模拟获取结果
            result = Integer.valueOf(new Random().nextInt(100));
            //唤醒wait的对象
            synchronized (this){
                LockSupport.unpark(currRun);
            }
            System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end!");
        } catch (Exception e) {
            logger.error("thread execute error info:{},{}",e.getMessage(),e);
        }
    }

    public static void main(String[] args) throws Exception {
        ThreadResultTest callback = new ThreadResultTest(Thread.currentThread());
        final String threadName = "Thread-Name";
        Thread thread = new Thread(callback, threadName);
        thread.start();
        // 循环检测线程的值
        while (true) {
            if (callback.getResult() == null) {
                System.out.println("execute result : " + callback.getResult());
                LockSupport.park();
            }
            if (callback.getResult() != null) {
                logger.info("execute check up info : " + callback.getResult());
                break;
            }
        }
    }
}

输出结果:

5、使用Callable获取线程的值

/**
 * @author chuan
 * @title: ThreadResultTest
 * @description: TODO(获取Thread的返回值-Callable)
 */
public class ThreadResultTest implements Callable<Object> {

    @Override
    public Object call() throws Exception {
        System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec start ...");
        Thread.sleep(2000);
        // 模拟获取结果
        Object result = Integer.valueOf(new Random().nextInt(100));
        System.out.println(String.format("thread " + Thread.currentThread().getName()) + " exec end ! ");
        return result;
    }

    public static void main(String[] args) throws Exception {
        ThreadResultTest callback = new ThreadResultTest();
        ExecutorService es = Executors.newSingleThreadExecutor();
        Future<Object> future = es.submit(callback);
        System.out.println("execute result:"+future.get());
        es.shutdown();
    }
}

输出结果:

这样就能很简单的获取到线程的值,获取返回值的方式是future.get(),这是一个阻塞方法;在子线程执行完(return)之前会一直阻塞。Callable本身就一接口,没什么玄机,玄机在 Future 或者说FutureTask上。

FutureTask是Future接口和Runnable接口的实现类。FutureTask是怎么和Callable关联上的?

  1. 经ExecutorService的作用,Callable会最终赋值给FutureTask的成员变量
  2. 通过查看源码、可以得出经过一系列调用过程,最终会调用Callable的call方法

其中get()是获取值的,它的逻辑并不复杂:

  • 判断状态,如果此时还未执行完,或者说还未给成员变量outcome(call() 方法返回值的引用)赋值,阻塞
  • 如果此时已经给outcome赋值,则将该对象返回

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值