关于java线程池理解


               线程池


为什么要使用线程池?

答:都知道多线程的特点是同时处理多个任务,也就是并行工作,然而多线程处理消耗的时间有创建线程时间1、工作时间2、销毁线程3;那如果能把创建和销毁的时间消耗减少,那么性能是不是能提高呢?答案是肯定的!那么这就是线程池的特点,就是节约了创建和销毁线程的时间消耗;

线程池的特点:

线程池在初始化的时候创建一定数量的线程,当需要线程执行任务的时候,再从线程池取出线程,执行完任务后,这些线程会回到线程池成为空闲线程,等待执行下一个任务;

认识线程,就必须认识队列:

1、ArrayBlockingQueue一个有数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序,队列的头部 是在队列中存在时间最长的元素,队列的尾部 是在队列中存在时间最短的元素,新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。

2、ConcurrentLinkedQueue:一个基于链接节点的无界线程安全队列。此队列按照 FIFO(先进先出)原则对元素进行排序,队列的头部 是队列中时间最长的元素,队列的尾部 是队列中时间最短的元素,新的元素插入到队列的尾部,队列获取操作从队列头部获得元素,当多个线程共享访问一个公共 collection 时, ConcurrentLinkedQueue是一个恰当的选择,此队列不允许使用 null 元素。

3、LinkedBlockingQueue:一个基于已链接节点的、范围任意的BlockingQueue。此队列按 FIFO(先进先出)排序元素,队列的头部 是在队列中时间最长的元素,队列的尾部 是在队列中时间最短的元素,新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素,链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。

4、SynchronousQueue:一种阻塞队列,其中每个插入操作必须等待另一个线程的对应移除操作 ,反之亦然。

常用到的两种队列是  ArrayBlockingQueue  和  LinkedBlockingQueue

Java通过Executors工厂类提供了四种线程池

1、newCachedThreadPool 创建一个可缓存(可变大小)线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2、newFixedThreadPool 创建一个自定义长度线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建一个延迟线程池,支持定时及周期性任务执行。
4、newSingleThreadExecutor 创建一个单任务线程池,它只会用唯一的工作线程来执行任务;

如果这四个都不能满足你的需求,那么还有一个选择:ThreadPoolExecutor(自定义线程池)

废话不多说,小哥,上代码:

1、可缓存线程池(可变大小线程池):newCachedThreadPool

public class ExecutorSerivceDay {
    public static void main(String[] args) {
         
        //可变大小的线程池,根据实际情况动态的改变线程池的大小.
        //当我们需要顺序执行的时候,用单任务线程池。大的任务用可变大小线程池。小的任务用可变大小的线程池。
        ExecutorService ex = Executors.newCachedThreadPool();
         
        test a1 = new test("t1");
        test a2 = new test("t2");
        test a3 = new test("t3");
         
        ex.execute(a1);
        ex.execute(a2);
        ex.execute(a3);
        ex.shutdown();
    }
}
class test implements Runnable{
    private String name;
    public test(String name){
        this.name = name;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i=0;
        System.out.println(Thread.currentThread().getName()+"   "+name+"执行开始");
        while(i<5){
            System.out.println(i++);
        }
        System.out.println(Thread.currentThread().getName()+"   "+name+"执行成功");
         
    }
     
}

2、自定义长度线程池:newFixedThreadPool

public class FixedThread {
    public static void main(String[] args) {
         
        /*
         固定尺寸线程池,这个参数里面写几个,线程就只有几个,
        如果Executors.newFixedThreadPool(1) 和  Executors.newSingleThreadExecutor();意思差不多
        单任务线程池,只能有一个线程在线程池里面
        suspend()方法:暂时挂起线程
        resume()方法:恢复挂起的线程
        stop()方法:停止线程
        */
        ExecutorService ex = Executors.newFixedThreadPool(3);
        test4 a1 = new test4("a1");
        test4 a2 = new test4("a2");
        test4 a3 = new test4("a3");
         
        ex.execute(a1);
        ex.execute(a2);
        ex.execute(a3);
         
        ex.shutdown();
    }
}
class test4 implements Runnable{
 
    private String name;
    test4(String name){
        this.name = name;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i=0;
        System.out.println(Thread.currentThread().getName()+"   "+name+"开始执行");
        while(i<5){
            System.out.println(i++);
        }
        System.out.println(Thread.currentThread().getName()+"   "+name+"执行完成");
    }
     
}

 
  

3、缓存线程池:newScheduledThreadPool

public class Scheduled {
    public static void main(String[] args) {
         
        //延时线程池
        ScheduledExecutorService se = Executors.newScheduledThreadPool(2);
         
        test2 a1 = new test2("a1");
        test2 a2 = new test2("a2");
        test2 a3 = new test2("a3");
         
        //参数:1、线程对象     2、延时时间  3、延时时间类型(TimeUnit.SECONDS为秒)。
        se.schedule(a1, 15, TimeUnit.SECONDS);
        se.schedule(a2, 1, TimeUnit.SECONDS);
        se.schedule(a3, 5, TimeUnit.SECONDS);
         
        se.shutdown();
    }
}
class test2 implements Runnable{
 
    private String name;
    test2(String name){
        this.name = name;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i=0;
        System.out.println(Thread.currentThread().getName()+"   "+name+"开始执行");
        while(i<5){
            System.out.println(i++);
        }
        System.out.println(Thread.currentThread().getName()+"   "+name+"执行完成");
         
    }
     
}

4、单任务线程池:newSingleThreadExecutor

class task implements Runnable{
    private String name;
    public task(String name){
        this.name = name;
    }
    public void run(){
        int i =0;
        System.out.println(Thread.currentThread().getName()+name+"开始执行");
        while(i<5){
            System.out.println(i++);
        }
        System.out.println(Thread.currentThread().getName()+name+"执行完成");
    }
}
public class TicketDemo{
    public static void main(String args[])
    {
        ExecutorService threadpool = Executors.newSingleThreadExecutor();
         
        task t1 = new task("t1");
        task t2 = new task("t2");
        task t3 = new task("t3");
         
        threadpool.execute(t1);
        threadpool.execute(t2);
        threadpool.execute(t3);
        threadpool.shutdown();          
             
    }
}

5、自定义线程池:ThreadPoolExecutor

public class ThreadPool {
    public static void main(String[] args) {
         
        //自定义线程池
         
        //BlockingQueue有数组支持的有界的阻塞队列——先进先出。
        BlockingQueue work = new ArrayBlockingQueue<>(3);//下面注解的队列线程数是这里的参数
         
        ThreadPoolExecutor tp = new ThreadPoolExecutor(2, 4, 100, TimeUnit.SECONDS, work);
         
        /*
        参数注解: new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue)
        参数corePoolSize:核心线程数,如果线程数<=队列线程数+corePoolSize那么就创建创建线程共corePoolSize个数 !注意:这个创建,是从头到尾只有那么几个。
        参数maximumPoolSize:允许创建的最大线程数,在线程数>队列线程数+corePoolSize的时候,就将corePoolSize扩充到maximumPoolSize那么大;
        参数keepAliveTime:当线程数大于核心线程数时,此为终止前多余的空闲线程等待新任务的最长时间。
        参数unit:时间单位;
        参数workQueue:工作线程等待队列;
        */
     
        test3 a1 = new test3("a1");
        test3 a2 = new test3("a2");
        test3 a3 = new test3("a3");
        tp.execute(a1);
        tp.execute(a2);
        tp.execute(a3);
        tp.shutdown();
    }
}
class test3 implements Runnable{
 
    private String name;
     
    test3(String name){
        this.name = name ;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        int i=0;
        System.out.println(Thread.currentThread().getName()+"   "+name+"开始执行");
         
        while(i<5){
            System.out.println(i++);
        }
         
        System.out.println(Thread.currentThread().getName()+"   "+name+"执行成功");
    }
     
}


那么现在代码也知道了,还有一个问题就是:我特么怎么知道应该用哪个线程池?
答案在这里~
答:1、当我们需要顺序执行的时候,用单任务线程池。
      2、当我们需要完成一个大任务,需要很多线程来执行的时候,就用可变大小线程池。
      3、如果对一些线程进行一些限制,比如延时操作的时候,就用延时线程池
      4、自定义线程池,适用于很多时候,这个线程池因为是自己定义的,所以很多时候都能满足自己对线程的需求。

原创:kiter



你可能感兴趣的:(java)