java如何异步方式处理业务逻辑

1.基础类-java.util.concurrent.ExcutorService

这个类的几个重要函数

shutdown 关闭任务池,无法传入新任务

shutdownnow 关闭所有任务,包括未执行完成的任务

submit 向任务池提交任务

2.基础接口-java.util.concurrent.Future

Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。

FutureTask 是实现了Future接口和Runnable接口,RunnableFuture接口

public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        Future<Integer> result = executor.submit(task);
        executor.shutdown();
         
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
         
        System.out.println("主线程在执行任务");
         
        try {
            System.out.println("task运行结果"+result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
         
        System.out.println("所有任务执行完毕");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子线程在进行计算");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}
--------------------------------------------------------------------------
public class Test {
    public static void main(String[] args) {
        //第一种方式
        ExecutorService executor = Executors.newCachedThreadPool();
        Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        executor.submit(futureTask);
        executor.shutdown();
         
        //第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
        /*Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
        Thread thread = new Thread(futureTask);
        thread.start();*/
         
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
         
        System.out.println("主线程在执行任务");
         
        try {
            System.out.println("task运行结果"+futureTask.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
         
        System.out.println("所有任务执行完毕");
    }
}
class Task implements Callable<Integer>{
    @Override
    public Integer call() throws Exception {
        System.out.println("子线程在进行计算");
        Thread.sleep(3000);
        int sum = 0;
        for(int i=0;i<100;i++)
            sum += i;
        return sum;
    }
}
----------------------------------------------------------------------------------
3.StaticMethod.getResult方法的优化版本,异步方式
/**
     * getResult 的优化版本 异步,非阻塞方式
     * @author jwjw233233@163.com
     * @param url 接口地址
     * @param param 接口参数
     */
    public static void getResult_Asynchronous(final String url, final String param) {
        ExecutorService es = Executors.newCachedThreadPool();
        es.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                PrintWriter out = null;
                BufferedReader in = null;
                String result = "";
                try {
                    URL realUrl = new URL(url);
                    // 打开和URL之间的连接
                    URLConnection conn = realUrl.openConnection();
                    // 设置通用的请求属性
                    conn.setRequestProperty("accept", "*/*");
                    conn.setRequestProperty("connection", "Keep-Alive");
                    conn.setRequestProperty("user-agent",
                            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                    // 发送POST请求必须设置如下两行
                    conn.setDoOutput(true);
                    conn.setDoInput(true);

                    // 获取URLConnection对象对应的输出流
                    out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
                    // 发送请求参数
                    out.print(param);
                    // flush输出流的缓冲
                    out.flush();
                    // 定义BufferedReader输入流来读取URL的响应
                    in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                    String line;
                    while ((line = in.readLine()) != null) {
                        result += line;
                    }
                } catch (Exception e) {
                    System.out.println("发送POST请求出现异常!" + e);
                    System.out.println("url=" + url + "?" + param);
                }
                // 使用finally块来关闭输出流、输入流
                finally {
                    try {
                        if (out != null) {
                            out.close();
                        }
                        if (in != null) {
                            in.close();
                        }
                    } catch (IOException ex) {
                    }
                }
                return result;
            }

        });
        es.shutdown();
    }

----------------------------------------------------------------------------

测试函数

public static void main(String[] args) {
        System.out.println(new Date());
        StaticMethod.getResult_Asynchronous("http://cs.jiwu.com/build!home.action?bid=3343", "");
        System.out.println(new Date());
        
        System.out.println(new Date());
        StaticMethod.getResult("http://cs.jiwu.com/build!home.action?bid=3343", "");
        System.out.println(new Date());
    }

输出结果:

Fri Apr 15 14:41:22 CST 2016
Fri Apr 15 14:41:22 CST 2016
Fri Apr 15 14:41:22 CST 2016
Fri Apr 15 14:41:32 CST 2016

---------------------------------------------------------------------------------------------------------

 结论:采用异步方式更新一个楼盘页 几乎不需要等待,而采用同步方式却花费了10s的时间,性能有巨大差距!

原文地址:https://www.cnblogs.com/jiwuyf/p/5395466.html