Java多线程——<四>让线程有返回值

一、概述

  到目前为止,我们已经能够声明并使一个线程任务运行起来了。但是遇到一个问题:现在定义的任务都没有任何返回值,那么加入我们希望一个任务运行结束后告诉我一个结果,该结果表名任务执行成功或失败,此时该怎么办呢?

  答案是使用Callable。之前定义的任务都直接实现了Runnable,该接口的run方法并无返回值。而Callable的call方法可以根据你传入的泛型参数返回对应类型的数据。

二、实现

  1.实现Callable接口,定义可返回结果的线程任务

public class TaskCallable implements Callable<String>{
    private int id;
    public TaskCallable(int id){
        this.id = id;
    }
    @Override
    public String call() throws Exception {

        return "result of taskWithResult "+id;
    }
}

  注意,泛型参数String表示的是该任务执行之后返回结果的类型。

  2.将该任务交给线程执行者executor,让他来代理执行这些线程

ExecutorService exec = Executors.newCachedThreadPool();//工头
ArrayList<Future<String>> results = new ArrayList<Future<String>>();//
for(int i = 0 ; i < 10 ;i++){
    results.add(exec.submit(new TaskCallable(i)));//submit返回一个Future,代表了即将要返回的结果
}

  注意,此时需要使用executor的submit方法来调用Callable的call。

  该方法将返回一个Future接口的对象,它的泛型参数代表了call方法要返回的参数类型。

  3.Future类型

  简单的了解了下Future类型:按照名字判断该类型对象代表了线程执行完成后的结果,所以叫Future。那么在获取该类型存放的线程运行结果时,可能该线程并未运行完毕,所以称其为“将来的结果”。

  •   首先,可以用isDone()方法来查询Future是否已经完成,任务完成后,可以调用get()方法来获取结果
  •     如果不加判断直接调用get方法,此时如果线程未完成,get将阻塞,直至结果准备就绪

从线程中返回数据的两种方法

1、通过类变量和类方法返回数据

2、通过回调函数返回数据

3、实现 Callable<V>接口,其中 V 代表 返回值类型

一、通过变量和方法返回数据

先看如下一段代码

public class MyThread extends Thread
{
  private String value1;

  private String value2;

  public void run()
  {
  value1 = "value1";
  value2 = "value2";
  }

public static void main(String[] args)
{

MyThread t1 = new MyThread();
t1.start();
System.out.println(t1.value1);
System.out.println(t1.value2);
}

}

输出结果 :

null
null
1
2
上面的运行结果很不正常,在run方法中已经对value1和value2进行赋值,但是返回却是null。发生这种情况的原因是: 在调用strat()方法后就立即输出 value1 和 value2 的值,而这里的run 方法 还没有指定到value1 和 value2 赋值语句。

如果要避免这种情况,就需要等run方法执行完成后才输出 vaue1 和value2 代码。可以考虑使用sleep 将主线程进行延迟,但是有一个问题,你不知道需要延迟多久才能知道 value2 或 value1 有值 !!! 我们可以这样做,如下代码

public class MyThread extends Thread
{
private String value1;

private String value2;

public void run()
{
value1 = "value1";
value2 = "value2";
}

public static void main(String[] args) throws InterruptedException
{

MyThread t1 = new MyThread();
t1.start();

while(t1.value1 == null || t1.value1 == null)
{
sleep(100);
}
System.out.println(t1.value1);
System.out.println(t1.value2);
}

}

输出结果:

value1
value2
1
2
以上方法虽然帮助我们解决了问题,但是Java的线程模型为我们提供了更好的解决方案,就是使用join()方法,join()方法的功能 就是使线程 从异步执行 变成同步执行 。当线程变成同步执行后,就跟普通方法中得到返回数据没什么区别了。

public static void main(String[] args) throws InterruptedException
{

MyThread t1 = new MyThread();
t1.start();
t1.join();
System.out.println(t1.value1);
System.out.println(t1.value2);
}

二、通过回调函数返回数据

跟 通过回调方法向线程传递 数据的 思路一致

三、实现 Callable 接口

1、定义任意类并实现 Callable 接口,并实现 方法 V call() throws Exception。其中,v 皆是代表返回值类型

2、在 V call() throws Exception 方法里 定义 方法体,并 return 一个返回值

3、创建线程池,创建任务对象,线程池通过submit(任务对象) 执行任务,并返回一个 Future<V> 对象

4、通过Future对象.get() 方法获取返回值

5、关闭线程池,释放资源

public class MyThread implements Callable<String>
{

private String value;

public MyThread(String value)
{
this.value = value;
}

public String call() throws Exception
{

System.out.println(Thread.currentThread().getName());//pool-1-thread-1
return "线程返回值是:"+this.value;
}

public static void main(String[] args)
{

//创建一个线程池对象
ExecutorService pool = Executors.newCachedThreadPool();

//创建一个有返回值的任务
MyThread task = new MyThread("Java");

//执行任务并获取Future对象
Future<String> future = pool.submit(task);

//从 Future 对象 获取任务返回值
while(true)
{
//可以用isDone()方法来查询Future是否已经完成,任务完成后,可以调用get()方法来获取结果
//注意: 如果不加判断直接调用get方法,此时如果线程未完成,get将阻塞,直至结果准备就绪
if(future.isDone())
{
try
{

String returnValue = future.get().toString();

System.out.println("线程返回值:"+returnValue);

}catch (Exception e){

e.printStackTrace();
}

//关闭线程池
pool.shutdown();

//跳出循环
break;
}

}

}

}
---------------------
作者:YFL_iOS
来源:CSDN
原文:https://blog.csdn.net/qq_18505715/article/details/78726164
版权声明:本文为博主原创文章,转载请附上博文链接!

原文地址:https://www.cnblogs.com/Alex80/p/11123567.html

时间: 2024-11-10 21:36:19

Java多线程——<四>让线程有返回值的相关文章

Java多线程——&lt;三&gt;让线程有返回值

一.概述 到目前为止,我们已经能够声明并使一个线程任务运行起来了.但是遇到一个问题:现在定义的任务都没有任何返回值,那么加入我们希望一个任务运行结束后告诉我一个结果,该结果表名任务执行成功或失败,此时该怎么办呢? 答案是使用Callable.之前定义的任务都直接实现了Runnable,该接口的run方法并无返回值.而Callable的call方法可以根据你传入的泛型参数返回对应类型的数据. 二.实现 1.实现Callable接口,定义可返回结果的线程任务 public class TaskCal

python多线程获取子线程任务返回值

今天想实现多线程更新资产信息,所以使用到了threading,但是我需要每个线程的返回值,这就需要我在threading.Thread的基础上进行封装 def auto_asset(node): ret = salt.remote_grains_execution_sigle(node) asset_info={} asset_info['os']= ret[node]['oscodename'] asset_info['kernelrelease']= ret[node]['kernelrel

Java多线程之~~~Callable接口获得返回值

ThreadPoolExecutor提供了另一个非常强有力的接口,那就是callable.这个接口和runnable类似,但是实现这个 接口的方法是call方法,这个方法是可以返回值的,弥补了runnable不能返回值的悲哀.而且这个方法可以配合ThreadP oolExecutor使用,获得Future接口,从这个接口的名字我们就能知道,返回的这个类似于指向这个线程的一个指针,我 们能通过这个Future接口知道当前线程的运行情况,包括是否已经完成任务,目前运行情况,运行完成后的返回值等, 而

在Java 线程中返回值的用法

http://icgemu.iteye.com/blog/467848 在Java 线程中返回值的用法 博客分类: Java Javathread 有时在执行线程中需要在线程中返回一个值:常规中我们会用Runnable接口和Thread类设置一个变量:在run()中改变变量的值,再用一个get方法取得该值,但是run何时完成是未知的:我们需要一定的机制来保证. 在在Java se5有个Callable接口:我们可以用该接口来完成该功能: 代码如: Java代码   package com.thr

java多线程四种实现方法

package com.zrun.TestThread; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Exec

线程的返回值

线程的返回值当线程退出时,线程可以选择向主线程返回一个值,返回方式一共有4种1\如果要返回int类型,可以使用pthread_exit((int)* return_value);2\使用全局变量返回(这个最简单)3\使用malloc所分配的空间4\直接返回字符串,如pthread_exit("return value"); #include <stdio.h> #include <stdlib.h> #include <string.h> #incl

Java多线程之后台线程不执行finally

后台线程不执行finally package wzh.daemon; import java.util.concurrent.TimeUnit; class ADaemon implements Runnable { @Override public void run() { try { System.out.println("Starting ADaemon"); TimeUnit.SECONDS.sleep(1); } catch (Exception e) { System.ou

Java多线程之后台线程

将线程设置成后台线程Daemons 主线程结果后,后台线程将自动结果. package wzh.test; import java.util.concurrent.TimeUnit; class SimpleDaemons implements Runnable{ @Override public void run() { try { while (true) { TimeUnit.MILLISECONDS.sleep(100); System.out.println(Thread.curren

java线程池的自带监控,线程池返回值的控制

当使用java线程池的时候,返回值类型用future<T> 来接收,比如: Future<String> future = fixedThreadPool.submit(new Thread());返回的结果必须由线程执行完毕后才会返回,我们可以利用这一点进行线程堵塞,监控线程的结束时间. package com.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.