最近项目用到一个功能需要实现多线程分发任务且需要任务的返回值,之前一直都是实现Runnable接口,但里面的run方法是返回void的。后来在网上查了下JAVA1.5开始就有了Callable。

下面来看看如何倒腾下这个东西。

import java.util.concurrent.Callable;

/**
* @类说明 线程业务处理
* @author DavenTsang
* @date 2016-11-16
*
*/
public class PoolTask implements Callable<String> { private String id; @Override
public String call() throws Exception {
return "当前线程名:" + Thread.currentThread().getName() + ":" + id;
} public String getId() {
return id;
} public void setId(String id) {
this.id = id;
} }

先建立一个类实现Callable接口。一下是JDK的API对Callable接口的描述:

public interface Callable<V>

返回结果并且可能抛出异常的任务。实现者定义了一个不带任何参数的叫做 call 的方法。

Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。

Executors 类包含一些从其他普通形式转换成 Callable 类的实用方法。

V是需要返回的对象。

需要执行这个实现类,我们需要创建一个线程池

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future; public class PoolUtils { //可伸缩线程池
private static ExecutorService cachedPool = Executors.newCachedThreadPool();
public static CompletionService<String> completionService = new ExecutorCompletionService<String>(cachedPool);
private PoolTask task;
public String addTask() throws InterruptedException, ExecutionException{
//添加任务
Future<String> future = completionService.submit(task);
//检查是否出现第二个线程进来
Thread.sleep(1000);
List<Future<String>> list = new ArrayList<Future<String>>();
System.out.println(completionService.take().get());
list.add(future);
return completionService.take().get();
} public PoolTask getTask() {
return task;
}
public void setTask(PoolTask task) {
this.task = task;
} }

Thread.sleep();调用这个方法是因为在前面添加任务是用一个线程数组调用,看下Executors.newCachedThreadPool();这个是否可以自己去根据需要创建线程。

我们再来看下submit()方法的源码,

public Future<V> submit(Callable<V> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<V> f = newTaskFor(task);
executor.execute(new QueueingFuture(f));
return f;
}
  private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}

追一下源码会发现里面有个队列存在。submit添加一个任务就会放到队列里面。这样就不用我们显示的去创建一个队列。

调用类:

import java.util.concurrent.ExecutionException;

public class Test {

    public static void main(String[] args) throws InterruptedException, ExecutionException {
Thread[] thread = new Thread[10];
for(int i = 0;i<thread.length;i++){
thread[i] = new Thread(new A());
}
for(Thread th : thread){
th.start();
} }
} class A implements Runnable{
@Override
public void run() {
PoolTask task = new PoolTask();
task.setId("daven");
PoolUtils utils = new PoolUtils();
utils.setTask(task);
try {
String a = utils.addTask();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}

调用类用多个线程去调用是因为模拟项目的场景了。

以上是一些记录供自己回忆用。遇到问题先自己查找原因,再去网上找下然后再找API追源码。

Callable实现JAVA多线程的更多相关文章

  1. Java多线程系列--“JUC线程池”06之 Callable和Future

    概要 本章介绍线程池中的Callable和Future.Callable 和 Future 简介示例和源码分析(基于JDK1.7.0_40) 转载请注明出处:http://www.cnblogs.co ...

  2. java:多线程基础之Runnable、Callable与Thread

    java.lang包下有二个非常有用的东西:Runnable接口与Thread类,Thread实现了Runnable接口(可以认为Thread是Runnable的子类),利用它们可以实现最基本的多线程 ...

  3. java多线程Future和Callable类的解释与使用

    一,描写叙述 ​在多线程下编程的时候.大家可能会遇到一种需求,就是我想在我开启的线程都结束时,同一时候获取每一个线程中返回的数据然后再做统一处理,在这种需求下,Future与Callable的组合就派 ...

  4. java多线程系列(七)---Callable、Future和FutureTask

    Callable.Future和FutureTask 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java多线程系列(一)之java多线程技能 java多线程系列(二)之对象变量 ...

  5. java多线程创建-Thread,Runnable,callable和threadpool

    java创建多线程的方式有许多种,这里简要做个梳理 1. 继承Thread类 继承java.lang.Thread类,创建本地多线程的类,重载run()方法,调用Thread的方法启动线程.示例代码如 ...

  6. java多线程(三)-Executors实现的几种线程池以及Callable

    从java5开始,类库中引入了很多新的管理调度线程的API,最常用的就是Executor(执行器)框架.Executor帮助程序员管理Thread对象,简化了并发编程,它其实就是在 提供了一个中间层, ...

  7. Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四)

    java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)java多线程同步以及线程间通信详解&消费者生产者模式&死锁& ...

  8. java多线程开发,Executors、FutureTask、Callable

    java多线程如何应用呢,几乎学java的同学都知道Thread类和Runable接口.继承Thread类或者实现Runable接口,调用thread的start方法即可启动线程. 然后是线程池,就是 ...

  9. Java多线程 - Callable和Future

    已知的创建多线程的方法有继承Tread类和实现Runnable方法.此外Java还提供了Callable接口,Callable接口也提供了一个call()方法来做为线程执行体.但是call()方法与r ...

随机推荐

  1. oop面向对象【接口、多态】

    今日内容 1.接口 2.三大特征——多态 3.引用类型转换 教学目标 1.写出定义接口的格式 2.写出实现接口的格式 3.说出接口中成员的特点 4.能够说出使用多态的前提条件 5.理解多态的向上转型 ...

  2. (办公)记事本_Linux权限

    参考谷粒学院Linux教程:http://www.gulixueyuan.com/course/300/task/7084/show# linux权限,什么用户可以操作什么. 1.基本权限的作用: 1 ...

  3. OD 快捷方式及窗口说明

    OD 快捷方式 其他窗口 L : log 保存日志信息 E :程序的所有模块的信息(加载基址,大小,OEP,路径) M :程序的内存映射视图 T :线程信息 W :窗口信息 H :句柄表 C :CPU ...

  4. ES-结构化查询

    参考: https://es.xiaoleilu.com/054_Query_DSL/55_Request_body_search.html 请求体查询 GET /_search {} 分页 GET ...

  5. MySQL数据库:合并结果集

    合并结果集 union----合并结果集 对合并后的结果集中的重复数据也会自动去重 select sName from students union select tName from Teacher ...

  6. Java_map的key为自定义对象

    首先自定义Key对象 import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import java ...

  7. CodeForces - 460C(二分+差分)

    题意 https://vjudge.net/problem/CodeForces-460C 一个长度为 n 的序列 a ,你有 m 次操作的机会,每次操作是将其中连续的 w 个元素增加 1 .最大化最 ...

  8. 《Web Development with Go》Mangodb查询collection内所有记录

    相当于select * from table; package main import ( "fmt" "log" "time" " ...

  9. 项目如何部署在linux系统上

    前面已经安装好centos的系统,网络配置,以及部署的环境已成功啦... 下面记录的是如何部署一个项目 四个步骤: (1)放war包 (2)执行数据库脚本 (3)修改数据库的配置文件 (4)重启tom ...

  10. 【Spring JDBC】NamedParameterJdbcTemplate(四)

    一.什么是具名参数 在经典的 JDBC 用法中, SQL 参数是用占位符 ? 表示,并且受到位置的限制.定位参数的问题在于, 一旦参数的顺序发生变化, 就必须改变参数绑定.在 Spring JDBC ...