JAVA多线程与高并发实战 第一讲:线程内容的特点

177 阅读4分钟

1. 前言

开篇:真正的大师永远都怀着一颗学徒的心 --无极剑圣 易

为什么写!第一,以我的工作经历说起,跟过创业团队老板自称2000亿项目(真的一脸尴尬),做过外包总结如下:外包没有权,没有归属感,随时可能提桶跑路,沟通强势,说了这么多废话!!!总之一切的问题都是自己的问题,打铁还需自身硬,这几年为了还款只要给钱的活我从来不挑,导致忽略了工作本身带给我的价值(鼠目寸光就是这么来的),我相信应该会有很多人和我一样,或者说我是个反面教材,回顾过去感觉自己做的事情也不少但是总是零零散散,没有体系化,张口就忘,况且我相信有很多人还是CRUD,说是搞什么SOA,服务治理你想想你真的这些事是你做的吗?哪怕自己用电脑搭建过框架吗?为了解决这个BUG我会从多线程高并发慢慢更新,有的是我自己总结有的是之前学习的笔记,如果有哪里不对联系我更改!

选择博客的原因: 我的职业规划很符合现在所在的团队,我认为这是我这些年来在工作中做的最正确的一次选择,如果后续发展良好,我可能会需要单独带项目,单独对接,公司有大哥在,我压力也是比较大!我希望建立知识体系化内容,SOA,搜索引擎,消息中间件,数据库优化,利用常用的技术框架搭建完整的项目(再考虑可能不会以博客方式发主要关注各大框架技术吧),JVM调优(这个先往后放放),等等等等,我会争取三个月时间从0到1和大家一起学习,我也边学边巩固。这个也是为了如果发展良好我会在项目中对公司业务日后做定点培训,建立一套完整的学习规范出来,也是给我自己做一做职业规划,没了开始学习!

高并发与多线程,整体要做的知识点、后续可能上具体业务,到时候再说先要知道有什么! 多线程与高并发.png

面包会有的,牛奶会有的,一切都会有的!

2. 线程的历史--CPU被无情压榨的惨案(不重要)

  • 单进程人工切换 - 纸带机
  • 多进程批处理 - 多个任务批量执行
  • 多进程并行处理 - 把程序写在不同的内存位置上来回切换
  • 多线程 - 程序内部不同任务的来回切换 selector(NIO的多路复用) epoll(epoll是Linux内核为处理大批量文件描述符而作了改进的poll - 百度百科)IO的知识后面会说!

3. 面试题

先看图:画起来很累的!觉得帮助点个赞支持一下! image.png

  1. 什么是进程?
    进程是资源分配的基本单位
  2. 什么是线程?
    线程是调度执行的基本单位,通俗的说!一个程序的不同路径,线程是在进程内部。多个线程共享同一个进程里的资源。
  3. 什么是线程的切换?

image.png 4. 单核CPU设定多线程是否有意义?
有! 线程在一段时间内执行不是所有情况都消耗CPU资源,而是有可能在等待资源,网络IO等待,这个期间就可以做线程切换(这问题有面试官问?我是没遇到过这么无聊的,当然为什么要写,从头讲咱们就从头来,结合网上的帖子和自己学习的) 扩展:CPU密集型、IO密集型线程,字面意思一个计算一个传输
5. 线程数是不是设置的越大越好?
那必然不是!因为线程切换也是消耗资源的,上代码 CountDownLatch不用太关注后面再讲!主要看m1、

private static final double[] nums = new double[1_0000_0000];
private static final Random r = new Random();
private static final DecimalFormat df = new DecimalFormat("0.00");

static {
    for (int i = 0; i < nums.length; i++) {
        nums[i] = r.nextDouble();
    }
}

private static void m1() {
    long start = System.currentTimeMillis();
    double result = 0.0;
    for (double num : nums) {
        result += num;
    }
    long end = System.currentTimeMillis();
    System.out.println("m1:" + (end - start) + "result = " + df.format(result));
}

static double result1 = 0.0, result2 = 0.0, result = 0.0;

private static void m2() {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < nums.length / 2; i++) {
            result1 += nums[i];
        }
    });
    Thread t2 = new Thread(() -> {
        for (int i = nums.length / 2; i < nums.length; i++) {
            result2 += nums[i];
        }
    });
    long start = System.currentTimeMillis();
    t1.start();
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    result = result1 + result2;
    long end = System.currentTimeMillis();
    System.out.println("m2:" + (end - start) + "result = " + df.format(result));
}

private static void m3() {
    final int threadCount = 2;
    Thread[] threads = new Thread[threadCount];
    double[] results = new double[threadCount];

    final int segmentCount = nums.length / threadCount;
    CountDownLatch latch = new CountDownLatch(threadCount);
    for (int i = 0; i < threadCount; i++) {
        int m = i;
        threads[i] = new Thread(() -> {
            for (int j = m * segmentCount; j < (m + 1) * segmentCount; j++) {
                results[m] += nums[j];
            }
        });
        latch.countDown();
    }
    double results3 = 0.0;
    long start = System.currentTimeMillis();
    for (Thread t : threads) {
        t.start();
    }
    for (double v : results) {
        results3 += v;
    }
    try {
        latch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    long end = System.currentTimeMillis();
    System.out.println("m3:" + (end - start) + "result = " + df.format(result));
}

public static void main(String[] args) {
    m1();
    m2();
    m3();
}
  1. 工作线程数设多少合适?
    公式网上有很多!简单来说 核数 * CPU利用率 * (1+等待/计算时间)怎么知道 W/C时间?JProfiler(工具) image.png
  2. 纤程/协程
    绿色线程:用户管理的,不是操作系统管理的线程
  3. 什么是程序? App.exe(这有人不知道?)我为什么写!艹!

4. 总结:

讲了一些常见面试题,计算机底层线程运行!下一节,创建线程的方式敬请期待!