首先讲解一下获取线程池的3种方法:1、newFixedThreadPool;2、newSingleThreadExecutor;3、newCachedThreadPool
newFixedThreadPool:创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,大多数线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,如果需要的话,那么一个新线程将代替它执行后续的任务。在某个线程被显式地关闭之前,池中的线程将一直存在。
newSingleThreadExecutor:创建一个使用单个 worker线程的 Executor,以无界队列方式来运行该线程。如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与newFixedThreadPool不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。
newCachedThreadPool:创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。
下面讲解一个实例:
1. MainActivity.java
package com.example.test_s_c;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.new一个线程管理队列
DownloadTaskManager.getInstance();
//2.new一个线程池,并启动
DownloadTaskManagerThread downloadTaskManagerThread = new DownloadTaskManagerThread();
new Thread(downloadTaskManagerThread).start();
//3.请求下载
String []items=new String[]{"任务1","任务2","任务3","任务1"};
for(int i=0;i<items.length;i++){
DownloadTaskManager downloadTaskMananger = DownloadTaskManager
.getInstance();
downloadTaskMananger.addDownloadTask(new DownloadTask(items[i]));
try {
Thread.sleep(2500);//给刚添加的任务一段执行的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
2.DownloadTask.java
package com.example.test_s_c;
import android.util.Log;
public class DownloadTask implements Runnable{
public String name;
public DownloadTask(String name){
this.name=name;
}
@Override
public void run() {
Log.i("ThreadTest", "正在执行下载任务:"+ this.getFileId());
try {
Thread.sleep(1000);//真实项目中应该在此处书写要完成的下载的任务逻辑,此处使用睡眠一段时间代替
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("ThreadTest", "执行完成下载任务:"+ this.getFileId());
}
public String getFileId(){
return name;
}
}
3.DownloadTaskManager.java
package com.example.test_s_c;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import android.util.Log;
public class DownloadTaskManager {
private static final String TAG="DownloadTaskManager";
// 线程队列
private LinkedList<DownloadTask> downloadTasks;
// 任务队列用来管理线程队列
private Set<String> taskIdSet;
private static DownloadTaskManager downloadTaskMananger;
private DownloadTaskManager() {
downloadTasks = new LinkedList<DownloadTask>();
taskIdSet = new HashSet<String>();
}
public static synchronized DownloadTaskManager getInstance() {
if (downloadTaskMananger == null) {
downloadTaskMananger = new DownloadTaskManager();
}
return downloadTaskMananger;
}
public void addDownloadTask(DownloadTask downloadTask) {
synchronized (downloadTasks) {
if (!isTaskRepeat(downloadTask.getFileId())) {
// 增加下载任务
downloadTasks.addLast(downloadTask);
}
}
}
public boolean isTaskRepeat(String fileId) {
synchronized (taskIdSet) {
if (taskIdSet.contains(fileId)) {
return true;
} else {
Log.i("ThreadTest", "taskIdSet增加下载任务:"+ fileId);
taskIdSet.add(fileId);
return false;
}
}
}
public DownloadTask getDownloadTask() {
synchronized (downloadTasks) {
if (downloadTasks.size() > 0) {
DownloadTask downloadTask = downloadTasks.removeFirst();
Log.i("ThreadTest", "取出下载任务:"+ downloadTask.getFileId());
return downloadTask;
}
}
return null;
}
}
4.DownloadTaskManagerThread.java
package com.example.test_s_c;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.util.Log;
public class DownloadTaskManagerThread implements Runnable {
private DownloadTaskManager downloadTaskManager;
// 创建一个可重用固定线程数的线程池
private ExecutorService pool;
// 线程池大小
private final int POOL_SIZE = 5;
// 轮询时间
private final int SLEEP_TIME = 1000;
// 是否停止
private boolean isStop = false;
public DownloadTaskManagerThread() {
downloadTaskManager = DownloadTaskManager.getInstance();
pool = Executors.newFixedThreadPool(POOL_SIZE);
}
@Override
public void run() {
// TODO Auto-generated method stub
while (!isStop) {
DownloadTask downloadTask = downloadTaskManager.getDownloadTask();
if (downloadTask != null) {
pool.execute(downloadTask);//执行线程队列中的指定的任务线程
} else { //如果当前未有downloadTask在任务队列中
try {
// 查询任务完成失败的,重新加载任务队列
// 轮询,
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (isStop) {
pool.shutdown();
}
}
public void setStop(boolean isStop) {
this.isStop = isStop;
}
}
5.执行结果
注意:如果在MainActivity.java中将Thread.sleep(2500);中的2500改为1000的话,就有可能出现下面各个线程任务的执行重叠的情况,因为没有留出足够的时间让上一个线程执行完成,下一个线程就开始要执行了。