java线程池的创建使用

时间:2023-03-08 16:40:51

  利用java的多线程编程可以大大的提高系统的并发运行效率,线程越多并发执行的任务就越多,但是并不意味着效率会一直提高,相反会得到适得其反的效果。

  java中的多线程编程一共有三种方法:

    继承Thread类

    继承Runnable接口

    使用线程池Executor

  下面简单的介绍一些Executor的使用

 一、话不多说先上代码:

  创建一个线程数为3的线程池,模拟十个任务让线程池调度线程去完成。

 package executorExample;

 import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class Threads{
private static final int nThreads = 3;
private int i;
public void Thread(){
//实现ExecutorService接口创建 线程数为三个的线程池
ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
for (i = 0; i < 10; i++) {
//在匿名内部类中变量index还在必须把index声明成final类型
final int index = i;
executorService.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
String threadName = Thread.currentThread().getName();//获取当前线程的名字
System.out.println(threadName+"正在执行任务:"+index);
}
});
}
}
public static void main(String[] args){
Threads thread = new Threads();
thread.Thread();
}
}

  接下来解释一下这段代码。在这段代码当中用到的关键词有ExcutorService,Executors,newFixedThreadPool和execute方法,还有一个最重要的Executor,现在来解释一下他们之间的关系

1、Executors

  首先我们先看一下Executors的源码

 public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());

public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
 public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
    return new FinalizableDelegatedExecutorService
      (new ThreadPoolExecutor(1, 1,
                    0L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>(),
                    threadFactory));
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}

  里面有四种都是ExecutorService类型的线程池,也就是说,我们在创建线程池的时候可以有四种选择,newCachedThreadPool,newFixedThreadPool,newSingleThreadExecutor,newWorkStealingPool。其中最常用的就是newCatchedThreadPool和newFixedThreadPool,可以看到每个线程池的参数队列是不同的,LinkedBlockingQueue<Runnable>()属于无边界队列,

  (1)newFixedThreadPool

    是一个固定线程数的线程池,当线程池里线程满了之后,下载任务就会被阻塞到等待下载队列里面等待下载。而LinkedBlockingQueue<Runnable>()无限扩容的FIFO规则的队列,我们在编程的时候一般用它比较多。

  (2)newCatchedThreadPool

    是一个可缓存线程池,如果线程池里的线程数超过了处理需要,则线程池可以灵活的回收空闲的线程,

  别的线程池就先不介绍了

2、ExecutorService

 public interface ExecutorService extends Executor {

  在接口ExecutorService的源码中我们可以看到继承了Executor类,并且在ExecutorService方法中实现了

    

void shutdown();
invokeAll();
submit();

  等等的方法。

3、Executor

 public interface Executor {

     void execute(Runnable command);
}

  在接口Executor中只有一个execute()方法,这是用来将任务提交给线程的。

到这里就明白了他们之间的关系,这样可以帮助我们更好的利用线程池去提高我们的代码效率。

写的不是很完善,如果有大神,希望多多指教,写这个东西也是为了自己能够更熟练的使用线程池。