(总结)线程实现的三种方式(Thread、Runable、Callable)

这里主要是对Callable使用方式的总结

一、Thread的使用

Thread  thread = new Thread();
thread.start();

二、Runable的使用

private void test(){
 new Thread(new MyRunnable()).start();
}
class MyRunnable implements Runnable{
@Override
public void run() {
 //TODO 编写逻辑
 }
}

三、Callable的使用

Callable< T >要与Feture< T >一起使用,适用于Java SE5 之上。
下面举几个例子:

1、基本用法:

private void test() throws Exception{
    CallableTest taskWithResult = new CallableTest();
    //FutureTask的众多实现接口中有一个是Future接口
    FutureTask<String> futureTask = new FutureTask<String>(taskWithResult);
    new Thread(futureTask).start();
    //get()方法如果有结果会立刻得到,如果暂时没有结果则会一直阻塞等待线程完成
    String value = futureTask.get();
    System.out.println("结果:"+value);
}
class CallableTest implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "返回结果";
    }
}

2、添加到线程池:

private void test() throws Exception{
    ExecutorService executorService = Executors.newSingleThreadExecutor();
    CallableTest taskWithResult = new CallableTest();
    Future<String> future = executorService.submit(taskWithResult);
    executorService.shutdown();
    //get()方法如果有结果会立刻得到,如果暂时没有结果则会一直阻塞等待线程完成
    String value = future.get();
    System.out.println("结果:"+value);
}

class CallableTest implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "返回结果";
    }
}

3、添加多个任务到线程池中:

private void test(){
//暂时没想到怎么动态获取线程数量,ThreadPoolExecutor里面有一些方法可以参考获取,但是并不能保证总是正确
//在ExecutorCompletionService源码里的样例是通过自己维护一个集合,来进行数量的判断
    ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newCachedThreadPool();
    CallableTest taskWithResult = new CallableTest();
    CompletionService<String> cs = new ExecutorCompletionService<String>(es);
    cs.submit(taskWithResult);//添加第一个任务
    cs.submit(taskWithResult);//添加第二个任务
    es.shutdown();
    for (int i = 0;i < 2;i++){
        try {
            Future<String> future = cs.take();
            String value = future.get();
            System.out.println("结果:"+value);
        }catch (InterruptedException | ExecutionException e){
            e.printStackTrace();
        }
    }
}

class CallableTest implements Callable<String>{
    @Override
    public String call() throws Exception {
        return "返回结果";
    }
}

Callable使用的场景:
假如在主线程里面要执行一个耗时操作(暂时认为A),这个耗时操作执行完之后拿到结果又回主线程进行下一步操作(暂时认为C)。在子线程执行耗时操作的同时主线程还在执行任务(暂时认为B)。要求就是任务B要在任务A和任务C都执行完之后执行。这种方式使用Callable的话就比较合适,下面画了一个草图:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Mr_Tony/article/details/78952520