您的位置:首页 > 移动开发 > Android开发

Android 价值千万java多线程同步 <二>Callable和Future&FutureTask

2017-03-24 14:40 507 查看


1).Android 价值千万   java线程专题:Wait¬ify&join&Yield

http://blog.csdn.net/whb20081815/article/details/65627387

2).Android 价值千万    java多线程同步 <二>Callable和Future&FutureTask

http://blog.csdn.net/whb20081815/article/details/65630694

3).Android 价值千万    java多线程<三>生产者消费者模型四种实现方法

http://blog.csdn.net/whb20081815/article/details/65635647

 4).


Android 价值千万    java多线程同步 <四> synchronized&Lock&Atomic6种方式


http://blog.csdn.net/whb20081815/article/details/66971983


5).Android 价值千万java多线程同步 <五>CountDownLatch(计数器)和Semaphore(信号量)

http://blog.csdn.net/whb20081815/article/details/68498371

Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Android中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。

Runnable

其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中,该函数没有返回值
public
interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see     java.lang.Thread#run()
*/
public abstract void run();
}

Callable

Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是call()函数有返回值,


Callable接口类似于Runnable,从名字就可以看出来了,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值

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;
}

可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。




Future

Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行

取消、查询是否完成、获取结果、设置结果操作

public interface Future<V> {

/**
* Attempts to cancel execution of this task.  This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run.  If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}.  Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);

FutureTask

FutureTask则是一个RunnableFuture<V>,而RunnableFuture实现了Runnbale又实现了Futrue<V>这两个接口,

FutureTask实现了两个接口,Runnable和Future,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。

并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、

Runnable,又是包装了Callable( 如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。

使用的实例:AsyncTask的源码分析!

public class FutureTask<V> implements RunnableFuture<V> {

public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}


4者关系的2中组合:

第一种组合模式:Callable,FutureTask,Future的组合

Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return task(20);
}
};
FutureTask<Integer> future = new FutureTask<Integer>(callable);
new Thread(future).start();


第二种组合模式:ExecutorService
,Future,Callable


try {
ExecutorService mExecutor = Executors.newSingleThreadExecutor();
FutureTask<Integer> futureTask = new FutureTask<Integer>(
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return task(20);
}
});
// 提交futureTask
/**FutureTask此时做为Runnable来用,Future是线程池的返回值*/
Future <?> futureTest=mExecutor.submit(futureTask);
//            futureTest.get();
Log.d(TAG, "future result from futureTask : "
+ futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}


实例:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testRunnable();
testCallable();
testFutureTask();
testFutureTaskThread();
}


/**
* runnable, 无返回值
*/
public void testRunnable(){

new Thread(new Runnable() {
@Override
public void run() {

Log.d(TAG,"testRunnable"+task(20));

}
}).start();

}


public void testCallable(){

try {
/**
* 提交runnable则没有返回值, future没有数据
*/
ExecutorService mExecutor = Executors.newSingleThreadExecutor();
Future<?> result = mExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return task(20);
}
});
Log.d(TAG,"future result from runnable :"+result.get());
} catch (Exception e) {
e.printStackTrace();
}

}


public void testFutureTask(){

/**
* FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口,
* 另外它还可以包装Runnable(实际上会转换为Callable)和Callable
* <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行
* ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。
*/
try {
ExecutorService mExecutor = Executors.newSingleThreadExecutor();
FutureTask<Integer> futureTask = new FutureTask<Integer>(
new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return task(20);
}
});
// 提交futureTask
/**FutureTask此时做为Runnable来用,Future是线程池的返回值*/
Future <?> futureTest=mExecutor.submit(futureTask);
//            futureTest.get();
Log.d(TAG, "future result from futureTask : "
+ futureTask.get());
} catch (Exception e) {
e.printStackTrace();
}

}


/**
* FutureTask 和Thread的关系用法
*/
public void testFutureTaskThread(){

Callable<Integer> callable = new Callable<Integer>() { public Integer call() throws Exception { return task(20); } }; FutureTask<Integer> future = new FutureTask<Integer>(callable); new Thread(future).start();

}


AS源代码地址:不知道为什么传不上去
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: