使用Thread创建10000个线程,并运行,记录时间:
public class ThreadPoolTest {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<Thread> threads = new ArrayList<>(10000);
for (int i = 0; i < 10000; i++) {
Thread thread = new Thread();
threads.add(thread);
thread.start();
}
for(Thread t:threads){
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ms:"+(System.currentTimeMillis() - startTime));
}
}
结果: ms:1761
使用线程池:
public class ThreadPoolTest2 {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
int size = 10000;
ExecutorService executorService = Executors.newSingleThreadExecutor();
final CountDownLatch countDownLatch = new CountDownLatch(size);
for (int i = 0; i < size; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
countDownLatch.countDown();
}
});
}
try {
countDownLatch.await();//等待10000计数结束
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.shutdown();
System.out.println("ms:" + (System.currentTimeMillis() - startTime));
}
}
结果: ms:69
两者相差的时间为100倍以上,这边使用的线程池回头再来看,由这个例子可以看出,线程的创建到运行过程,会花费大量的cpu时间,争对需要大量并发的操作,使用线程池可以大大提高程序性能
Executors是个帮助类,内部实际使用的是ThreadPoolExecutor,构造函数如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
ThreadPoolExecutor大致的执行场景如下:
execute方法执行流程
再来看构造函数中各个参数的含义:
任务队列实现BlockingQueue接口,JDK提供了以下4种:
后台一般不允许使用Executors,但我们安卓开发是可以使用的,接下来来使用Executors三种线程池,有了上面ThreadPoolExecutor的了解,理解起来很简单
public class ThreadPoolTest3 {
public static void main(String[] args) {
ExecutorService executorService1 = Executors.newCachedThreadPool();
ExecutorService executorService2 = Executors.newFixedThreadPool(10);
ExecutorService executorService3 = Executors.newSingleThreadExecutor();
for (int i = 1; i <= 100; i++) {
executorService1.execute(new TestRunnable(i));
// executorService2.execute(new TestRunnable(i));
// executorService3.execute(new TestRunnable(i));
}
}
static class TestRunnable implements Runnable {
int i = 0;
public TestRunnable(int i) {
this.i = i;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
newCachedThreadPool方法如下:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
它和直接创建线程类似,可以创建无限的线程
newFixedThreadPool方法如下:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
它拥有指定大小的核心线程数,并且只有核心线程,以及一个无限大小的任务队列
newSingleThreadExecutor方法如下:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
它仅有一个核心线程,以及一个无限大小的任务队列,所以相当于单线程执行任务队列中的任务