我想网上面一大堆关于线程池的文章和资料,这里面介绍一些需要注意和最好能够了解的部分.
一般使用线程池就会想到类ExecutorService和Executors
不知道是否有人看过他们的源代码,他们的关系如下:
public interface ExecutorService extends Executor
当然可以知道Executors也是个接口:
public interface Executor {
这个里面个人觉得需要注意ExecutorService.java中的
<T> Future<T> submit(Callable<T> task);
其中重点的Future类:
public interface Future<V> {
线程池管理着一堆的线程,如何获取这些线程运行状态呢?那么就需要了解Future类的作用了.我个人觉得这个类的作用主要是"占坑",当线程被submit的时候,返回一个Future对象,通过获取这个Future对象,并且调用其get()方法来获取线程的基本运行状态.虽然它能够让人知道线程池中的线程运行状态,但是由于这个状态是通过反馈回来的,如果线程池中的线程没有运行完,它就迟迟不会受到反馈信息,如果没有收到反馈信息,它就会阻塞它所在的线程,如果放在UI线程中,那么一旦运行,那么UI线程就会卡住,所以一般最好是放在异步线程中,比如说向服务确认身份认证,那么就要一直等待服务器反馈正确信息后,才能够执行向服务器请求的其他工作.
private void futureForPool(){
mPool=Executors.newFixedThreadPool(10);
Future<String> future=mPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2500);
Log.i(TAG,"future callback !");
return "zhibao.liu !";
}
});
try {
String msg=future.get().toString();
Log.i(TAG,"future msg : "+msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
另外一个FutureTask类:
public class FutureTask<V> implements RunnableFuture<V> {
public interface RunnableFuture<V> extends Runnable, Future<V> {
可以看出它也是Future机制的.
private void futureTaskForPool(){
mPool=Executors.newFixedThreadPool(10);
FutureTask<String> mft=new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2500);
Log.i(TAG,"FutureTask work !");
return null;
}
});
mPool.execute(mft);
try {
mft.get(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
} catch (ExecutionException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
} catch (TimeoutException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
}finally {
mPool.shutdown();
}
Log.i(TAG,"FutureTask i : finish !");
}
下面的需要注意:
mft.get(500, TimeUnit.MILLISECONDS);
线程中的任务需要在500ms时间的时候给出反馈,无论事情是否做完,如果事情还没有做完将会报出timeout异常,在处理异常中可以继续判断事情是否做完,如果没有做完,我们将其抛弃:
mft.cancel(true);
工作将不再继续执行.
就像食品有效日期一样,如果在有效日内,就可以继续食用,如果超出指定的有效日,就没有必要继续食用了.事情也是这样,有些事情只有在规定的时间内完成才有意义,如果超出了时间就没什么意义了.
下面给出整个工程源码:
package org.durian.durianexecutors;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class DurianMainActivity extends ActionBarActivity implements View.OnClickListener {
private final static String TAG="DurianMainActivity";
private Button mCachePoolButton;
private Button mFixPoolButton;
private Button mSchedulePoolButton;
private Button mSinglePoolButton;
private Button mFutureButton;
private Button mFactoryButton;
private ExecutorService mPool;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.durian_main);
mCachePoolButton=(Button)findViewById(R.id.cachepool);
mCachePoolButton.setOnClickListener(this);
mFixPoolButton=(Button)findViewById(R.id.fixpool);
mFixPoolButton.setOnClickListener(this);
mSchedulePoolButton=(Button)findViewById(R.id.schedulepool);
mSchedulePoolButton.setOnClickListener(this);
mSinglePoolButton=(Button)findViewById(R.id.singlepool);
mSinglePoolButton.setOnClickListener(this);
mFutureButton=(Button)findViewById(R.id.future);
mFutureButton.setOnClickListener(this);
mFactoryButton=(Button)findViewById(R.id.fixpoolforfactory);
mFactoryButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
int id=v.getId();
switch (id){
case R.id.future:
futureTaskForPool();
break;
case R.id.cachepool:
cachePoolForThread();
break;
case R.id.fixpool:
fixPoolForThread();
break;
case R.id.schedulepool:
schedulePoolForThread();
break;
case R.id.singlepool:
singlePoolForThread();
break;
case R.id.fixpoolforfactory:
fixPoolForFactoryThread();
break;
default:
break;
}
}
private int count=0;
private void futureForPool(){
mPool=Executors.newFixedThreadPool(10);
Future<String> future=mPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2500);
Log.i(TAG,"future callback !");
return "zhibao.liu !";
}
});
try {
String msg=future.get().toString();
Log.i(TAG,"future msg : "+msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
private void futureTaskForPool(){
mPool=Executors.newFixedThreadPool(10);
FutureTask<String> mft=new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2500);
Log.i(TAG,"FutureTask work !");
return null;
}
});
mPool.execute(mft);
try {
mft.get(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
} catch (ExecutionException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
} catch (TimeoutException e) {
boolean iswork=mft.isDone();
if(!iswork){
Log.i(TAG,"FutureTask is still working !");
}
mft.cancel(true);
// e.printStackTrace();
}finally {
mPool.shutdown();
}
Log.i(TAG,"FutureTask i : finish !");
}
private void cachePoolForThread(){
mPool=Executors.newCachedThreadPool();
count=0;
for(int i=0;i<20;i++){
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2500);
Log.i(TAG,"cachePoolForThread i : "+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
mPool.execute(thread);
}
}
private void fixPoolForThread(){
mPool=Executors.newFixedThreadPool(10);
count=0;
for(int i=0;i<10;i++){
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1500);
Log.i(TAG,"fixpool i="+count++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
Future<String> future=mPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(500);
Log.i(TAG,"future callback !");
return "zhibao.liu !";
}
});
try {
String msg=future.get().toString();
Log.i(TAG,"future msg : "+msg);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
mPool.execute(thread);
Future<String> m=mPool.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"future callback !");
}
},"durian from zhibao.liu");
try {
Log.i(TAG,"future msg : "+m.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
private void fixPoolForFactoryThread(){
count=0;
/*
* ThreadFactory : 作用
* <1> : 设置线程池中线程属性
* <2> : 代码debug
* <3> : 异常捕获
* */
mPool=Executors.newFixedThreadPool(10, new ThreadFactory() {
@Override
public Thread newThread(Runnable runable) {
Thread t=new Thread(runable);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
return t;
}
});
for (int i=0;i<10;i++){
mPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"fixPoolForFactoryThread work : "+count++);
}
});
}
}
private void schedulePoolForThread(){
ScheduledExecutorService schedule=Executors.newScheduledThreadPool(10);
count=0;
for (int i=0;i<1;i++){
Log.i(TAG,"schedule work ...");
schedule.schedule(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"schedule work after 1000 delays : "+count++);
}
},3000,TimeUnit.MILLISECONDS);
}
}
private void singlePoolForThread(){
mPool=Executors.newSingleThreadExecutor();
count=0;
for (int i=0;i<10;i++){
mPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"single work in the same thread : "+count++);
}
});
}
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="org.durian.durianexecutors.DurianMainActivity">
<Button
android:id="@+id/future"
android:text="future mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/cachepool"
android:text="newCachedThreadPool"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/fixpool"
android:text="newFixedThreadPool"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/schedulepool"
android:text="newScheduledThreadPool"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/singlepool"
android:text="newSingleThreadExecutor"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/fixpoolforfactory"
android:text="fixPoolForFactory"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
我们需要注意的是newSingleThreadExecutor返回的对象,这个我个人的理解是分配的N件事情,但是N件事情都是在同一个线程中完成的:从下面可以看出N件事情只在同一个线程中完成
Thread 1是app的主线程,Thread 6是虚拟机中的.
从Thread 28才是,只看见一个吧,下面给个cache的参照:从下面图中可以看出,N件事在N个线程中执行:
另外附加了一个FactoryThread
private void fixPoolForFactoryThread(){
count=0;
/*
* ThreadFactory : 作用
* <1> : 设置线程池中线程属性
* <2> : 代码debug
* <3> : 异常捕获
* */
mPool=Executors.newFixedThreadPool(10, new ThreadFactory() {
@Override
public Thread newThread(Runnable runable) {
Thread t=new Thread(runable);
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY);
return t;
}
});
for (int i=0;i<10;i++){
mPool.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"fixPoolForFactoryThread work : "+count++);
}
});
}
}
参照上面的注解,至于线程池中的四种应用,没什么特别要说的.