问题:当每次点击界面上的item触发开启一个子线程,去请求网络数据,界面上的item很多,在用户迅速点击的情况下, 会新建n个子线程, 每个线程在内存中占用1M空间, 消耗非常大,如何优化这种多线程任务?
解决方案: 用线程池去处理这种多线程的任务, 线程池的核心线程个数为1 ,用有界队列将新的线程添加进来,有界队列的size 也为1,即在线程池中 只能同时允许1个线程运行, 1个线程等待,在将新的线程添加进线程池之前, 先将线程池的队列清空,具体实现方案如下:
public class CountRunnable implements Runnable{
@Override
public void run() {
for(int i = 0 ; i < 5 ; i++){
System.out.println(Thread.currentThread().getName()+" i : "+i);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("---------------------------------");
}
}
int corePoolSize = 1;//核心线程个数
int maximumPoolSize = 1;//最大线程个数
long keepAliveTime = 5;//线程存活时间
TimeUnit unit = TimeUnit.SECONDS;
ArrayBlockingQueueworkQueue = new ArrayBlockingQueue<>(1);
ThreadPoolExecutor executor =new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,unit,workQueue);
//添加十个任务
for(int i = 1 ; i < 10; i++){
BlockingQueuequeue = executor.getQueue();
queue.clear();//添加任务之前,先将任务队列清空
System.out.println("blockQueue size : "+executor.getQueue().size());
executor.execute(new CountRunnable());
}
System.out.println("## blockQueue size : "+executor.getQueue().size());
上面所做的操作实际就是:用线程池去处理这种多线程的任务, 线程池的核心线程个数为1 ,用有界队列将新的线程添加进来,有界队列的size 也为1,即在线程池中 只能同时允许1个线程运行, 1个线程等待,在将新的线程添加进线程池之前, 先将线程池的队列清空, 输出的log可以看到, 虽然在运行的过程中添加了10个线程任务, 但是实际上只运行完成了两个线程任务:
blockQueue size : 0
blockQueue size : 0
blockQueue size : 0
blockQueue size : 0
blockQueue size : 0
pool-1-thread-1 i : 0
blockQueue size : 0
blockQueue size : 0
blockQueue size : 0
blockQueue size : 0
## blockQueue size : 1
pool-1-thread-1 i : 1
pool-1-thread-1 i : 2
pool-1-thread-1 i : 3
pool-1-thread-1 i : 4
---------------------------------
pool-1-thread-1 i : 0
pool-1-thread-1 i : 1
pool-1-thread-1 i : 2
pool-1-thread-1 i : 3
pool-1-thread-1 i : 4
---------------------------------
通过这种方式, 不管用户如何点击界面上的item ,实际上页面所需要的数据是用户最后一次点击item所返回回来的数据, 这样就避免了创建n个不必要的线程任务.