多线程(三)

继上一次讲的开始说吧。

new ThreadPoolExecutor() 自定义参数,理解每个参数什么含义,具体到某些业务场景,还要看具体怎么用。在此,再解释下核心线程数跟最大线程数到底有什么作用。举个例子:

new ThreadPoolExecutor(1,2,60,TimeUnit.Days,ArrayBlockingQueue),这个ArrayBlockingQueue  = new ArrayBlockingQueue(4),某个业务场景,需要执行7个sql,交给了ThreadExecutor来执行,ThreadExecutor 核心线程数只有1个,所以ThreadExecutor会执行第一个sql,这时候没执行完,剩下的6个sql 会放到queue中,由于ArrayBlockingQueue是个有界队列,最多只会放下4个任务, (LinkedBlockingQueue是无界队列,所以想放多少任务都可以),剩下两个任务,ThreadPoolExecutor 会用 max线程数-核心线程数,直接new 对象去执行。上面例子,因为最多有2个线程,核心线程只有一个,所以还有一个线程,程序发现,我线程不够用啊,因为还有两个子任务,那我就报错吧。

demo:

public class UseThreadExecutorPool implements Runnable {
    private static AtomicInteger count = new AtomicInteger();

    @Override
    public void run() {
        int all = count.incrementAndGet();
        System.out.println(all);
    }

    //自定义线程池  各个参数什么意思 corePoolSize 核心线程数,maximumPoolSize 最大线程数,
    //当 任务数量 <= corePoolSize 直接执行,    maximumPoolSize =>任务数量 > corePoolSize ,任务数量-corePoolSize 的任务 加到queue里面,拿corePoolSize 线程执行,
    // maximumPoolSize < 任务数量  在不超过 maximumPoolSize的情况下 新建线程执行 加满queue之后的 任务,当超过了最大线程数,就报错,
    public static void main(String[] args) {
        ArrayBlockingQueue arrayBlockingQueue = new ArrayBlockingQueue<UseThreadExecutorPool>(4);
        ExecutorService executorService = new ThreadPoolExecutor(1, 2, 60, TimeUnit.DAYS, arrayBlockingQueue);

        UseThreadExecutorPool useThreadExecutorPool0 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool1 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool2 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool3 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool4 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool5 = new UseThreadExecutorPool();
        UseThreadExecutorPool useThreadExecutorPool6 = new UseThreadExecutorPool();

        executorService.execute(useThreadExecutorPool0);
        executorService.execute(useThreadExecutorPool1);
        executorService.execute(useThreadExecutorPool2);
        executorService.execute(useThreadExecutorPool3);
        executorService.execute(useThreadExecutorPool4);
        executorService.execute(useThreadExecutorPool5);
        executorService.execute(useThreadExecutorPool6);

        executorService.shutdown();
    }
}
,当然呢,这个错误是可以自己处理的,详细看上一篇博客。

-----------------------------------------------------------------------------

下面谈谈CyclicBarrier 、CountDownLatch 和 信号量。

先说下CyclicBarrier 和CountDownLatch吧。这俩都可以实现实时通知,类似于分布式的并行计算,区别就是CyclicBarrier 是唤起多个线程,CountDownLatch唤起一个线程,举例个业务场景,运动五个跑步选手比赛,发令枪没响之前,各自干各自的事,喝水啊,绑鞋带啊,但是喊准备的时候,就统一听发令员的枪声了,下面看下例子

public class UseCyclicbarrier {
    static class Runner implements Runnable {
        private CyclicBarrier barrier;
        private String name;

        public Runner(CyclicBarrier barrier, String name) {
            this.barrier = barrier;
            this.name = name;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(5000);
                System.out.println(name + " 准备好了 ");
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(name + "go");
        }
    }

    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        executor.submit(new Thread(new Runner(barrier, "小明")));
        executor.submit(new Thread(new Runner(barrier, "小白")));
        executor.execute(new Thread(new Runner(barrier, "小红")));
        executor.shutdown();
    }
}
CyclicBarrier 初始化后面写个3,意思就是对象得调用三次await()方法,才能一同唤起,做自己的操作,两个就不行,会一直等待。三个线程都准备好了,才一起开始。这就是CyclicBarrier 。记住,CyclicBarrier 是唤起子线程,下面讲的CountDownLatch 是唤起一个线程,类似于统计的操作,举个CountDownLatch的demo

public class UseCountDownLatch {
    public static void main(String[] args) {
        final CountDownLatch countDownLatch = new CountDownLatch(2);

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("进入t1 等待其他线程执行完毕");
                try {
                    countDownLatch.await();
                    System.out.println("执行完毕");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("进入t2 ");
                try {
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("进入t3 ");
                try {
                    countDownLatch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        t2.start();
        t3.start();
    }
}
可以把代码粘贴到自己的编辑器里面,自己慢慢体会这两者的区别

信号量:说到信号量,不得不说的一个词叫分流,限流,这是在应用架构中经常性听到的词,什么意思呢,就是一个应用系统最大能承受10个客户,当前有20个客户,可以从网络层限制,也可以从服务层限制,还可以从java层面去限制,java层面就是用的信号量,信号量可以定义当前可以处理多少个请求,达到分流的效果。服务层呢可以用nginx做分流,限流。网络层的话 类似于cdn做镜像,这也是分流,限流的一种策略。代码不展示了,百度下一堆,知道什么意思就行。

下面说说英文单词;

pv:每个页面的访问量,不计算单个ip,刷新一个即计数。

uv:最小请求单位(ip,每天只统计一次)

qps(tps):每秒请求数 

rt:每个request请求的返回时间。

这些名词,有可能在做自动化测试的时候提到。

----------------------------------------------------------------------------------------

下面说说  重入锁 跟 读写锁:也就是Lock 跟RetreentLock,这两者与sync 有什么区别呢,1.8以前sync性能不太好,1.8以后没区别,如果非要问1.8以后的区别的话,Lock锁更加简单化,随性化。RetreentLock 试用场景 读多写少 ,读少写多的话可以使用RetreentReadWriteLock  代码不展示,

还有两个锁是 readLock 跟 writeLock。记住一个方言就是,读读共享,读写互斥,写写互斥。

下篇博客谈谈disruptor并发框架。(一个很nb的并发框架)

      


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值