java 线程中的值如何返回

Python013

java 线程中的值如何返回,第1张

如果是java5的话,那么Java5新增了Callable接口获得线程返回值,用法如下

package com.ronniewang  

  

  

import java.util.concurrent.Callable  

import java.util.concurrent.ExecutionException  

import java.util.concurrent.ExecutorService  

import java.util.concurrent.Executors  

import java.util.concurrent.Future  

  

  

public class GetReturnValueFromCallable {  

  

  

    private static final int SLEEP_MILLS = 3000  

  

  

    private static final int SECOND_MILLS = 1000  

  

  

    private static int sleepSeconds = SLEEP_MILLS / SECOND_MILLS  

  

  

    ExecutorService executorService = Executors.newCachedThreadPool()  

  

  

    /** 

     * 在创建多线程程序的时候,我们常实现Runnable接口,Runnable没有返回值,要想获得返回值,Java5提供了一个新的接口Callable 

     */  

    public static void main(String[] args) {  

  

  

        new GetReturnValueFromCallable().testCallable()  

    }  

  

  

    private void testCallable() {  

  

  

        /** 

         * Callable需要实现的是call()方法,而不是run()方法,返回值的类型有Callable的类型参数指定, 

         * Callable只能由ExecutorService.submit() 执行,正常结束后将返回一个future对象 

         */  

        Future<String> future = executorService.submit(new Callable<String>() {  

  

  

            public String call() throws Exception {  

  

  

                Thread.sleep(SLEEP_MILLS)  

                return "I from callable"  

            }  

        })  

  

  

        while (true) {  

            /** 

             * 获得future对象之前可以使用isDone()方法检测future是否完成,完成后可以调用get()方法获得future的值, 

             * 如果直接调用get()方法,get()方法将阻塞值线程结束 

             */  

            if (future.isDone()) {  

                try {  

                    System.out.println(future.get())  

                    break  

                } catch (InterruptedException e) {  

                    // ignored  

                } catch (ExecutionException e) {  

                    // ignored  

                }  

            }  

            else {  

                try {  

                    System.out.println("after " + sleepSeconds-- + " seconds, we will get future")  

                    Thread.sleep(SECOND_MILLS)  

                } catch (InterruptedException e) {  

                    // ignored  

                }  

            }  

        }  

    }  

}  

package com.ronniewang

import java.util.concurrent.Callable

import java.util.concurrent.ExecutionException

import java.util.concurrent.ExecutorService

import java.util.concurrent.Executors

import java.util.concurrent.Future

public class GetReturnValueFromCallable {

    private static final int SLEEP_MILLS = 3000

    private static final int SECOND_MILLS = 1000

    private static int sleepSeconds = SLEEP_MILLS / SECOND_MILLS

    ExecutorService executorService = Executors.newCachedThreadPool()

    /**

     * 在创建多线程程序的时候,我们常实现Runnable接口,Runnable没有返回值,要想获得返回值,Java5提供了一个新的接口Callable

     */

    public static void main(String[] args) {

        new GetReturnValueFromCallable().testCallable()

    }

    private void testCallable() {

        /**

         * Callable需要实现的是call()方法,而不是run()方法,返回值的类型有Callable的类型参数指定,

         * Callable只能由ExecutorService.submit() 执行,正常结束后将返回一个future对象

         */

        Future<String> future = executorService.submit(new Callable<String>() {

            public String call() throws Exception {

                Thread.sleep(SLEEP_MILLS)

                return "I from callable"

            }

        })

        while (true) {

            /**

             * 获得future对象之前可以使用isDone()方法检测future是否完成,完成后可以调用get()方法获得future的值,

             * 如果直接调用get()方法,get()方法将阻塞值线程结束

             */

            if (future.isDone()) {

                try {

                    System.out.println(future.get())

                    break

                } catch (InterruptedException e) {

                    // ignored

                } catch (ExecutionException e) {

                    // ignored

                }

            }

            else {

                try {

                    System.out.println("after " + sleepSeconds-- + " seconds, we will get future")

                    Thread.sleep(SECOND_MILLS)

                } catch (InterruptedException e) {

                    // ignored

                }

            }

        }

    }

}

输出结果:

after 3 seconds, we will get future

 after 2 seconds, we will get future

 after 1 seconds, we will get future

 I from callable

可以通过实现Callable接口创建一个有返回值的线程,代码如下:

import java.util.concurrent.*

public class MyThread implements Callable<Integer> {

    private int count

    public MyThread(int count) {

        this.count = count

    }

    @Override

    public Integer call() throws Exception {

        // 此处是线程要处理的业务代码,此处实现的是对count变量加1的操作

        count += 1

        Thread.sleep(1000)

        return count

    }

    public static void main(String[] args) {

        // 创建线程实例

        MyThread myThread = new MyThread(1)

        // 创建一个大小为10的线程池

        ExecutorService executor = Executors.newFixedThreadPool(10)

        // 将线程提交到线程池执行

        Future<Integer> future = executor.submit(myThread)

        try {

            // 调用get方法获取线程执行结果,在线程执行完成前该方法会一直阻塞

            Integer result = future.get()

            System.out.println(result)

        } catch (InterruptedException e) {

            e.printStackTrace()

        } catch (ExecutionException e) {

            e.printStackTrace()

        }

//        try {

//            // 这种写法可以设置线程执行的超时时间,当线程超过指定的时间还未执行完成时会抛出TimeoutException异常

//            // 示例中表示线程超过1000毫秒还没执行完就会抛出超时异常

//            Integer result = future.get(1000, TimeUnit.MILLISECONDS)

//            System.out.println(result)

//        } catch (InterruptedException e) {

//            e.printStackTrace()

//        } catch (ExecutionException e) {

//            e.printStackTrace()

//        } catch (TimeoutException e) {

//            e.printStackTrace()

//        }

    }

}

软件模块之间存在调用的接口,从调用方式来看,有同步调用、回调、异步调用这三种方式:

同步调用是是一种阻塞式调用,调用方要等待被调用方执行完毕返回后才能获取调用的执行结果,是一种单向调用。

回调是一种双向调用,调用方在执行被调用方后,被调用方会调用被调用方的接口;

异步调用是一种类似消息或者事件的机制,接口在收到某个消息或发生某事件时,会主动通知客户方,通常使用回调来实现异步调用。

Java回调的必须要素: 

1.雇主类必须有可以被观察者调用的方法A; 

2.观察者必须持有可以调用A的对象的引用。

在实际工作中,我们通常将方法A以interface或者内部类的形式来实现,然后把包含有A的类的对象引用传递到观察者中。

Java中的线程的返回值是void,并且是一个异步执行流,所以我们没有直接的方法来获取线程执行后的结果,即不能直接知道线程何时结束,以及合适去获取线程执行任务后的结果。由于回调的存在,我们可以在线程中以回调的方式通知线程的调用者线程的结束时间,并可以将任务的结果通过回调回送到调用者中。