java 多线程-线程的两种创建方式-Callable-Future结合使用

Java多线程的主要两种方式

package main.com.imekaku;

import org.junit.Test;

/**
 * Created by liyuling(benzi) on 2017/6/13.
 * Class description :
 */
public class ThreadTest {

    @Test
    public void test1() {
        new Thread(new MyThread1()).start();

        Thread thread = new MyThread2();
        thread.start();
        System.out.println("end");
        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class MyThread1 implements Runnable {

    public void run() {
        long sum = 0;
        for (long i = 0; i < 1000000; i++) {
            sum += i;
        }
        System.out.println("implement: " + sum);
    }
}

class MyThread2 extends Thread {

    public void run() {
        long sum = 0;
        for (long i = 0; i < 1000000; i++) {
            sum += i;
        }
        System.out.println("extends: " + sum);
    }

}

实现Runnable方式,匿名对象(匿名对象匿名类)创建

    @Test
    public void test2() {
        new Thread(new Runnable() {
            public void run() {
                try {
                    Thread.currentThread().sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("hi");
            }
        }).start();
        System.out.println("end");
        try {
            Thread.currentThread().sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("real end");
    }

Callable和Future结合实现实现在执行完任务后获取返回值

    @Test
    public void test3() {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        Future<String> future = executorService.submit(new Callable<String>() {
            public String call() throws Exception {
                Thread.currentThread().sleep(3 * 1000);
                return "hello world";
            }
        });
        try {
            System.out.println(future.get()); // 线程在这里阻塞
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }

CompletableFuture 类使用

主动完成计算

CompletableFuture类实现了CompletionStage和Future接口,所以你还是可以像以前一样通过阻塞或者轮询的方式获得结果,尽管这种方式不推荐使用。参考地址:http://colobu.com/2016/02/29/Java-CompletableFuture/

    @Test
    public void test4() {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.currentThread().sleep(3 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Future Thread " + Thread.currentThread().getName());
            return 0;
        });
        System.out.println("Main Thread " + Thread.currentThread().getName());

        try {
            System.out.println(future.get()); // 阻塞的方式
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("end");
    }

创建CompletableFuture对象

四个静态方法用来为一段异步执行的代码创建CompletableFuture对象

public static CompletableFuture<Void> 	runAsync(Runnable runnable)
public static CompletableFuture<Void> 	runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> 	supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> 	supplyAsync(Supplier<U> supplier, Executor executor)

runAsync它以Runnable函数式接口类型为参数,所以CompletableFuture的计算结果为空。

supplyAsync方法以Supplier函数式接口类型为参数,CompletableFuture的计算结果类型为U。

计算结果完成时的处理

当CompletableFuture的计算结果完成,或者抛出异常的时候,我们可以执行特定的Action。主要是下面的方法。

可以看到Action的类型是BiConsumer< ? super T,? super Throwable>,它可以处理正常的计算结果,或者异常情况。

方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其它的线程去执行(如果使用相同的线程池,也可能会被同一个线程选中执行)。

注意这几个方法都会返回CompletableFuture,当Action执行完毕后它的结果返回原始的CompletableFuture的计算结果或者返回异常。

public CompletableFuture<T> 	whenComplete(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> 	whenCompleteAsync(BiConsumer<? super T,? super Throwable> action)
public CompletableFuture<T> 	whenCompleteAsync(BiConsumer<? super T,? super Throwable> action, Executor executor)
public CompletableFuture<T> 	exceptionally(Function<Throwable,? extends T> fn)
@Test
    public void test5() {
        CompletableFuture<Integer> completableFuture =
                CompletableFuture.supplyAsync(ExecutorServiceTest::getNum); // 该语句执行时,就调用了getNum方法
        Future<Integer> future =
                completableFuture.whenComplete((x, y) -> { // completableFuture 完成时,调用whenComplete方法
            System.out.println("running..");
            System.out.println("x = " + x); // x 表示ExecutorServiceTest::getNum 返回值
            System.out.println("y = " + y); // y 表示该过程异常
        });
        System.out.println("Main Thread is running.. " + Thread.currentThread().getName());
        try {
            System.out.println(future.get()); // 返回结果值
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    private static Integer getNum() {
        System.out.println(Thread.currentThread().getName() + " is running..");
        try {
            Thread.currentThread().sleep(3 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return (int) (Math.random() * 100);
    }
// 执行结果
ForkJoinPool.commonPool-worker-1 is running..
Main Thread is running.. main
running..
x = 70
y = null
70

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部