Java线程池

java的线程池:

1.线程池的作用:

限制程序执行线程的数量

2.为什么要用线程池:

  • 避免新开线程带来的开销,可以重复利用线程池里的线程
  • 用线程池,还可以降低内存的耗用,可根据服务器硬件情况初始线程池的大小
  • 创建线程的时间耗时为t1,执行任务的时间耗时为t2,销毁线程的时间耗时为t3,若t1+t3>t2即适合用线程池,以此来提高服务器性能

3.常用的线程池接口ExecutorService

线程池的顶级接口是Executor,从源码上来看是从jdk1.5开始的

《Java线程池》
《Java线程池》

public interface Executor {

    /**
     * Executes the given command at some time in the future.  The command
     * may execute in a new thread, in a pooled thread, or in the calling
     * thread, at the discretion of the {@code Executor} implementation.
     *
     * @param command the runnable task
     * @throws RejectedExecutionException if this task cannot be
     * accepted for execution
     * @throws NullPointerException if command is null
     */
    void execute(Runnable command);
}

View Code

但ExecutorService次接口里面定义了线程池大部分执行的方法,详看此接口的源码。
目前创建线程池由Executors类提供的静态方法提供,目的是减少创建线程池复杂性。涉及到创建线程池分为以下四种:

  • 1.newSingleThreadExecutor,详见以下源码:

《Java线程池》
《Java线程池》

    /**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

View Code

从源码上Creates an Executor that uses a single worker thread operating,就是创建一个单线程的线程池,即线程池里只有一个线程在工作;源码注释上还有一段话

* Creates an Executor that uses a single worker thread operating 
* off an unbounded queue. (Note however that if this single

* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.

即这个单线程串行执行任务的时候异常的时候且改线程关闭了,则重新new一个线程来继续执行任务。以下是demo代码:

《Java线程池》
《Java线程池》

public class MyThread extends Thread {
    @Override
    public void run(){
       Long threadId= Thread.currentThread().getId();
       String threadName=Thread.currentThread().getName();
       String now=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(System.currentTimeMillis());
       System.out.println("threadName:"+threadName+",threadId:"+threadId+",now:"+now);
    }
}

public class ThreadExecute {
    public static void main(String[] args) {
        ExecutorService service=Executors.newSingleThreadExecutor();
        MyThread t0=new MyThread();
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        service.submit(t0);
        service.submit(t1);
        service.submit(t2);
        service.shutdown();
    }
}

View Code

执行结果如下:

 《Java线程池》

 

  • 2.newFixedThreadPool,详见以下源码:

《Java线程池》
《Java线程池》

    /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue.  At any point, at most
     * {@code nThreads} threads will be active processing tasks.
     * If additional tasks are submitted when all threads are active,
     * they will wait in the queue until a thread is available.
     * If any thread terminates due to a failure during execution
     * prior to shutdown, a new one will take its place if needed to
     * execute subsequent tasks.  The threads in the pool will exist
     * until it is explicitly {@link ExecutorService#shutdown shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

View Code

从源码注释来看:

* Creates a thread pool that reuses a fixed number of threads 
* operating off a shared unbounded queue
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks.

 创建一个固定大小的线程池,每处理一个任务创建一个线程直到达到最大值,若其中有线程因为一场关闭了,则会重新生成一个线程来补上。以下是demo:

《Java线程池》
《Java线程池》

    public static void main(String[] args) {
        ExecutorService service=Executors.newFixedThreadPool(3);
        MyThread t0=new MyThread();
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        service.submit(t0);
        service.submit(t1);
        service.submit(t2);
        service.shutdown();
    }

View Code

执行结果如下:

《Java线程池》

  • 3.newCachedThreadPool,详见如下源码:

《Java线程池》
《Java线程池》

    /**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

View Code

/**  * Creates a thread pool that creates new threads as needed, but  
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to
{@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources.
 
 创建一个缓存的线程池,当任务增加时,可智能的新增线程,对于60s没有活动的线程将会移除,以下是demo:

《Java线程池》
《Java线程池》

public class ThreadExecute {
    public static void main(String[] args) {
        ExecutorService service=Executors.newCachedThreadPool();
        MyThread t0=new MyThread();
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();
        service.submit(t0);
        service.submit(t1);
        service.submit(t2);
        service.shutdown();
    }
}

View Code

执行结果如下:

《Java线程池》

  • 4.newScheduledThreadPool,详见如下源码:

《Java线程池》
《Java线程池》

    /**
     * Creates a thread pool that can schedule commands to run after a
     * given delay, or to execute periodically.
     * @param corePoolSize the number of threads to keep in the pool,
     * even if they are idle
     * @return a newly created scheduled thread pool
     * @throws IllegalArgumentException if {@code corePoolSize < 0}
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

View Code

 

* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
该返回值是:ScheduledExecutorService.且源码里new的是ScheduledThreadPoolExecutor创建初始大小的线程池,即使有线程处于空闲状态也不会移除掉,不像newCachedThreadPool有60s的非活动状态移除。
此线程正如注释一样,在delay(延时)后执行或者间隔性的重复执行。以下是demo:

《Java线程池》
《Java线程池》

    public static void main(String[] args) {
        ScheduledExecutorService service=Executors.newScheduledThreadPool(3);
        MyThread t0=new MyThread("t0");
        MyThread t1=new MyThread("t1");
        MyThread t2=new MyThread("t2");
        service.schedule(t0,1000,TimeUnit.MILLISECONDS);
        service.schedule(t1,2000,TimeUnit.MILLISECONDS);
        service.schedule(t2,3000,TimeUnit.MILLISECONDS);
        service.shutdown();
    }


public class MyThread extends Thread {
    private String name;
    public MyThread(String name) {
        this.name=name;
    }
    @Override
    public void run(){
        Long threadId= Thread.currentThread().getId();
        String threadName=Thread.currentThread().getName();
        String now=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(System.currentTimeMillis());
        System.out.println("this.name:"+this.name+",threadName:"+threadName+",threadId:"+threadId+",now:"+now);
    }
}

View Code

 

执行结果如下:

《Java线程池》

备注:此线程池与timer的区别很明显,前者可以多个线程同时处理,但timer是单线程串行处理

《Java线程池》
《Java线程池》

public class ThreadExecute {
    public static void main(String[] args) {
        ScheduledExecutorService service=Executors.newScheduledThreadPool(3);
        MyThread t0=new MyThread("t0");
        MyThread t1=new MyThread("t1");
        MyThread t2=new MyThread("t2");
        service.scheduleAtFixedRate(t0,1000,1000,TimeUnit.MILLISECONDS);
        service.scheduleAtFixedRate(t1,1000,2000,TimeUnit.MILLISECONDS);
        service.scheduleAtFixedRate(t2,1000,3000,TimeUnit.MILLISECONDS);
        //service.shutdown();
    }
}

View Code

执行结果如下:
《Java线程池》
  • 5.newWorkStealingPool,详见如下源码:

《Java线程池》
《Java线程池》

    /**
     * Creates a thread pool that maintains enough threads to support
     * the given parallelism level, and may use multiple queues to
     * reduce contention. The parallelism level corresponds to the
     * maximum number of threads actively engaged in, or available to
     * engage in, task processing. The actual number of threads may
     * grow and shrink dynamically. A work-stealing pool makes no
     * guarantees about the order in which submitted tasks are
     * executed.
     *
     * @param parallelism the targeted parallelism level
     * @return the newly created thread pool
     * @throws IllegalArgumentException if {@code parallelism <= 0}
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    /**
     * Creates a work-stealing thread pool using all
     * {@link Runtime#availableProcessors available processors}
     * as its target parallelism level.
     * @return the newly created thread pool
     * @see #newWorkStealingPool(int)
     * @since 1.8
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

View Code

 

* Creates a thread pool that maintains enough threads to support
* the given parallelism level, and may use multiple queues to
* reduce contention. The parallelism level corresponds to the
* maximum number of threads actively engaged in, or available to
* engage in, task processing. The actual number of threads may
* grow and shrink dynamically. A work-stealing pool makes no
* guarantees about the order in which submitted tasks are
* executed.
* since jdk1.8
创建一个并行大小的线程池,因为并行执行即不能保证每个线程执行的顺序。以下是demo:

《Java线程池》
《Java线程池》

public class ThreadExecute {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService service=Executors.newWorkStealingPool(3);
        List<Callable<String>> callables=Arrays.asList(
                ()->"t1",
                ()->"t2",
                ()->"t3"
                );
        service.invokeAll(callables).stream().map(future->{
            try {
                return future.get();
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "-1";
            } catch (ExecutionException e) {
                e.printStackTrace();
                return "-2";
            }
        }).forEach(System.out::println);
        service.shutdown();
    }
}

View Code

 

以下是运行结果:

《Java线程池》


备注:一般情况下用并行的情况,除非数据源TSource的数据量大,不超过万级别的话,个人觉得并行的意义不大

 

 
 
 
    原文作者:沙漠燃星
    原文地址: http://www.cnblogs.com/rootsoft/p/9007938.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞