线程池

作者: wanggs | 来源:发表于2018-12-23 20:47 被阅读0次

    1、为什么用线程池?

    • 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务
    • 根据系统的承受能力,调整线程池中工作线线程的数目,防止因为因为消耗过多的内存,而把服务
      器累趴下(每个线程需要大约 1MB 内存,线程开的越多,消耗的内存也就越大,最后死机)

    2、线程池参数的意思?

    比如去火车站买票, 有10个售票窗口, 但只有5个窗口对外开放. 那么对外开放的5个窗口称为核心线程数, 而最大线程数是10个窗口.如果5个窗口都被占用, 那么后来的人就必须在后面排队, 但后来售票厅人越来越多, 已经人满为患, 就类似于线程队列已满.这时候火车站站长下令, 把剩下的5个窗口也打开, 也就是目前已经有10个窗口同时运行. 后来又来了一批人,10个窗口也处理不过来了, 而且售票厅人已经满了, 这时候站长就下令封锁入口,不允许其他人再进来, 这就是线程异常处理策略.而线程存活时间指的是, 允许售票员休息的最长时间, 以此限制售票员偷懒的行为

    3.ThreadPoorExecutor原理?

    image.png 20180419002550514.jpg
    // 无边界队列,没有长度
            ConcurrentLinkedQueue clq = new ConcurrentLinkedQueue();
            // 入队
            clq.add(1);
            clq.add(2);
            clq.add(3);
            // 出对 并且在队列中移除
            System.out.println(clq.poll());
            System.out.println("队列数: " + clq.size());
            // 出对 不在队列移除
            System.out.println(clq.peek());
            System.out.println("队列数: " + clq.size());
            /**
             * 输出:
             * 1
             * 队列数: 2
             * 2
             * 队列数: 2
             */
             
             
     // 有界队列
            BlockingDeque bd = new LinkedBlockingDeque(2);
            // 入队
            bd.add(1);
            bd.add(2);
            System.out.println(bd.poll());
            // 3秒内是否放入进去
            bd.offer(3,3, TimeUnit.SECONDS);
            // 出对 并且在队列中移除
            System.out.println(bd.poll());
            System.out.println(bd.poll());
            System.out.println(bd.poll());
    
            /**
             * 1
             * 2
             * 3
             * null
             */
    
    image.png

    4、线程池实现

       public static void main(String[] args) throws InterruptedException {
            ThreadPoolExecutor tpe = new ThreadPoolExecutor(1,2,3,TimeUnit.SECONDS,new LinkedBlockingDeque<>(1));
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.shutdown();
            /**
             * pool-1-thread-1
             * pool-1-thread-2
             * pool-1-thread-1
             */
        }
    

    5、线程池实现

    • 定长
     ThreadPoolExecutor tpe = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.shutdown();
    
    • 缓存
    ThreadPoolExecutor tpe = (ThreadPoolExecutor) Executors.newCachedThreadPool();
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.execute(new ThreadTest());
            tpe.shutdown();
    
    • 定时
     ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
            for (int i = 0; i < 10; i++) {
                ses.schedule(new ThreadTest(), 3, TimeUnit.SECONDS);
            }
    
            ses.shutdown();
    /**
     * 3秒之后执行
     * pool-1-thread-1
     * pool-1-thread-2
     * pool-1-thread-1
     * pool-1-thread-2
     * pool-1-thread-1
     * pool-1-thread-2
     * pool-1-thread-2
     * pool-1-thread-1
     * pool-1-thread-2
     * pool-1-thread-1
     */
        }
    
    • 单例
            ExecutorService es = Executors.newSingleThreadExecutor();
            es.execute(new ThreadTest());
            es.execute(new ThreadTest());
            es.execute(new ThreadTest());
            es.shutdown();
    /**
     * pool-1-thread-1
     * pool-1-thread-1
     * pool-1-thread-1
     */
    
    image.png

    6、用过threadlocal吗?怎么用的

    订单处理包含一系列操作: 减少库存,增加一条流水账,修改总账,这几个操作要在同一个事务中操作,通常也就是在一个线程中处理,如果累加公司操作失败了,应把前面操作的回滚 ,否则提交所有操作,这要求这些操作使用相同的数据库连接对象,,而这些操作代码不在一个模块中。

    • ThreadLocal 的作用和目的: 用于实现线程内的数据共享,即相同的程序代码,在多个模块中运行,要共享同一份数据
    • 每个线程调用全局的ThreadLocal对象的set方法,首先根据当前的线程获取ThreadLocalMap对象,然后在map中掺入数据,key其实是ThreadLocal对象,vale 是各自方法传入的参数,
    image.png image.png

    7, volatile

    共享变量的可见性

    每个线程都有自己本地的内存空间,线程执行的时候先把变量从内存中读取到自己的内存空间中,然后对变量进行操作,对变量操作完成后,在某个时间再把变量刷新到主内存中

    image.png
    public class TestVolatile {
        
        public static void main(String[] args) {
            ThreadDemo td = new ThreadDemo();
            new Thread(td).start();
            while(true){
                if(td.isFlag()){
                    System.out.println("------------------");
                    break;
                }
            }
        }
    
    }
    
    class ThreadDemo implements Runnable {
        private  boolean flag = false;
        @Override
        public void run() {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
            }
            flag = true;
            System.out.println("flag=" + isFlag());
        }
    
        public boolean isFlag() {
            return flag;
        }
    }
    
    • 参考
    Java中volatile、synchronized和lock解析
    Java中volatile

    相关文章

      网友评论

          本文标题:线程池

          本文链接:https://www.haomeiwen.com/subject/epcokqtx.html