Java四种线程池及基础用法总结

一、为什么要用线程池:

1.节约系统资源,减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。

2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。

3.方便对线程进行管理。

new Thread的弊端

new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        }
    }
).start();

new Thread的缺点如下:

a. 每次new Thread新建对象性能差。 
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。 
c. 缺乏更多功能,如定时执行、定期执行、线程中断。

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

二、Java通过Executors提供四种线程池,分别为:

(1)newSingleThreadExecutor:创建一个单线程的线程池,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。此线程池支持定时以及周期性执行任务的需求。

(2)newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。

(3)newCachedThreadPool:创建一个可缓存的线程池,此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说 JVM)能够创建的最大线程大小。

(4)newScheduledThreadPool:创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

三、四种线程池的使用

1. newCachedThreadPool 
  创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

public static ExecutorService newCachedThreadPool() 
示例代码:

public class ThreadPoolExecutorTest {
     public static void main(String[]  args ) {
        ExecutorService cacheThreadPool =Executors.newCachedThreadPool();
         for(int i =1;i<=5;i++){
             final int index=i ;
             try{
                Thread.sleep(1000);
            }catch(InterruptedException  e ) {
                 e.printStackTrace();
            }
             cacheThreadPool.execute(new Runnable(){
                 @Override
                 public void run() {
                    System.out.println("第" +index +"个线程" +Thread.currentThread().getName());    
                }    
            });
        }
    }
}


//输出结果1个线程pool-1-thread-12个线程pool-1-thread-13个线程pool-1-thread-14个线程pool-1-thread-15个线程pool-1-thread-1   

由结果可看出 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。 
2. newFixedThreadPool 
  创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

public static ExecutorService newFixedThreadPool(int nThreads) 
nThreads - 池中的线程数

示例代码:

public class ThreadPoolExecutorTest {
     public static void main(String[] args) {
        ExecutorService  fixedThreadPool =Executors. newFixedThreadPool(3);
         for (int i =1; i<=5;i++){
             final int index=i ;
             fixedThreadPool.execute(new Runnable(){
                 @Override
                 public void run() {
                     try {
                        System.out.println("第" +index + "个线程" +Thread.currentThread().getName());
                        Thread.sleep(1000);
                    }  catch(InterruptedException  e ) {
                         e .printStackTrace();
                    }
                }

            });
        }
    }
}

由于设置最大线程数为3,所以在输出三个数后等待2秒后才继续输出。 
3. newScheduledThreadPool 
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 
corePoolSize - 池中所保存的线程数,即使线程是空闲的也包括在内。

延迟执行示例代码

public class ThreadPoolExecutorTest {    
    public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);      
        scheduledThreadPool.schedule(newRunnable(){         
            @Override 
            public void run() {
             System.out.println("延迟三秒");
             }
      }, 3, TimeUnit.SECONDS);
    }
}

表示延迟3秒执行。

定期执行示例代码


public class ThreadPoolExecutorTest {   
    public static void main(String[] args) {

        ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);       
    scheduledThreadPool.scheduleAtFixedRate(newRunnable(){        
        @Override            
        public void run() {
             System.out.println("延迟1秒后每三秒执行一次");
          }
     },1,3,TimeUnit.SECONDS);
 }

}

表示延迟1秒后每3秒执行一次。

4.newSingleThreadExecutor 
  创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1)不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。

public static ExecutorService newSingleThreadExecutor() 
示例代码

public class ThreadPoolExecutorTest {   
    public static void main(String[] args) {
        ExecutorService singleThreadPool= Executors.newSingleThreadExecutor();       
        for(int i=1;i<=5;i++){           
            int index=i;           
        singleThreadPool.execute(new Runnable(){
              @Override
              public void run() {                  
                try{
                 System.out.println("第"+index+"个线程");
                Thread.sleep(2000);
                 }catch(InterruptedException e) {                        
                    e.printStackTrace();
                }
            }  });
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37465368/article/details/80877619
今日推荐