欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java多线程之Callable接口的实现

程序员文章站 2022-05-05 22:10:07
...

一、基本理论

(1)Java 5.0 在 java.util.concurrent 提供了一个新的创建执行线程的方式:Callable 接口

(2)Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。如果我们希望任务完成之后有返回值,可以实现Callable接口。在JavaSE5中引入的Callable是一个具有类型参数的范型,他的类型参数方法表示为方法call()而不是run()中返回的值,并且必须使用ExecutorService.submint()方法进行调用

(3)Callable 需要依赖FutureTask ,FutureTask 也可以用作闭锁

二、代码实例

1、

//实现接口Callable 参数类型是String
public class TaskWithResult implements Callable<String> {
    private int id;
    public TaskWithResult(int id){
        this.id=id;
    }
    @Override
    public String call() throws Exception {
        return "result of TaskWithResult "+id;
    }
}
//java测试方法,基于junit4
@Test
    public  void main2() {
        ExecutorService exec= Executors.newCachedThreadPool();
       //Future接口后面有源码
        ArrayList<Future<String>> results=new ArrayList<Future<String>>();
        long start=System.currentTimeMillis();
        for(int i=0;i<10;i++){
            results.add(exec.submit(new TaskWithResult(i)));
        }
        //System.out.println("====================cost:"+(System.currentTimeMillis()-start));
        int count=0;
      //遍历数据
        for(Future<String> fs:results){
            //System.out.println("========cost:"+(System.currentTimeMillis()-start));
            long start2=System.currentTimeMillis();
            try{
              //取数据
                System.out.println(fs.get());

            }catch (InterruptedException e){
                System.out.print(e);

            }catch (ExecutionException e){
                System.out.print(e);
            }finally {
                exec.shutdown();

            }
            //System.out.println((count++)+"====================cost:"+(System.currentTimeMillis()-start2));

        }

    }

运行结果如下:
Java多线程之Callable接口的实现
2、

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/* * 一、创建执行线程的方式三:实现 Callable 接口。 
相较于实现 Runnable 接口的方式,方法可以有返回值,并且可以抛出异常。
 
* * 二、执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。  
* FutureTask 是  Future 接口的实现类 
* */

public class TestCallable {
	 public static void main(String[] args) {
	 ThreadDemo td = new ThreadDemo();

	 //1.执行 Callable 方式,需要 FutureTask 实现类的支持,用于接收运算结果。        
	 FutureTask<Integer> result = new FutureTask<>(td);

	new Thread(result).start();
	//2.接收线程运算后的结果        
	try {
		Integer sum = result.get();  //FutureTask 可用于 闭锁 类似于CountDownLatch的作用,在所有的线程没有执行完成之后这里是不会执行的            
		System.out.println(sum);            
		System.out.println("------------------------------------");
	}catch (InterruptedException | ExecutionException e) {
	e.printStackTrace();
	}
     }
}

class ThreadDemo implements Callable<Integer> {
	 @Override    
	 public Integer call() throws Exception {
	 int sum = 0;

	for (int i = 0; i <= 100000; i++) {
	 sum += i;
	}
	return sum;
     }
}

从上面的例子可以看到: Callable 和 Future接口的区别

(1)Callable规定的方法是call(),而Runnable规定的方法是run().
(2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
(3)call()方法可抛出异常,而run()方法是不能抛出异常的。
(4)运行Callable任务可拿到一个Future对象,Future表示异步计算的结果。
(5)它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
(6)通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
(7)Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。

三、Callable的接口源码

@FunctionalInterface
public interface Callable<V> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    V call() throws Exception;
}

四、Future 的接口源码

public interface Future<V> {
	//取消
	boolean cancel(boolean mayInterruptIfRunning);
	boolean isCancelled();
	//任务是否完成
	boolean isDone();
	//获得数据
	V get() throws InterruptedException, ExecutionException;
	V get(long timeout, TimeUnit unit)
	        throws InterruptedException, ExecutionException, TimeoutException;
}

参考自链接:https://www.jianshu.com/p/170fd03ab724
非常感谢!!!

相关标签: java 多线程