提升--01---线程基础知识

Posted 高高for 循环

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了提升--01---线程基础知识相关的知识,希望对你有一定的参考价值。

线程的历史

  • 之前的硬件,只有一个CPU
  • 之前的OS,只运行一个进程
  • 随着多核CPU的出现,人们开始追求对CPU效率的极致压榨
  • 多线程的程序随之诞生,但随之诞生的,也是非常难以应对的各种并发bug

进程 线程

多线程–01–程序、进程、线程

纤程/协程:绿色线程,用户管理的(而不是OS管理的)线程


- 什么是进程:资源分配的基本单位(静态概念)

- 什么是线程:资源调度的基本单位(动态概念)

- 通俗说:一个程序中不同的执行路径

线程的调度,切换线程也存在性能损耗

区分:

  • 程序:可执行文件,如xx.exe
  • 进程:资源分配的最小单位。一个程序可能由多个进程组成,进程启动后,操作系统会在内存中给进程分配空间
  • 线程:程序调度执行的最小单位,多个线程共享进程中的资源
  • 单线程:只有一条执行路径,一个执行任务
  • 多线程:有多条执行路径在同时运行,多个执行任务

一个java应用程序

一个java应用程序java.exe ,其实至少有三个线程:当然如果发生异常,会影响主线程

  • main线程
  • gc()垃圾回收线程
  • 异常处理线程

一个多线程程序一个进程,会先运行主线程,然后运行期间,再进行线程的切换,抢夺时间片.

1. 单核CPU设定多线程是否有意义

回答这个问题需要考虑,我们的线程被用来执行什么样的任务? 常见的任务分为两种:

  • CPU密集型任务
  • IO密集型任务

CPU密集型任务(CPU-bound):

  • 在一个任务中,主要做计算,CPU持续在运行,CPU利用率高,具有这种特点的任务称为CPU密集型任务。

IO密集型任务(IO-bound):

  • 在一个任务中,大部分时间在进行I/O操作,由于I/O速度远远小于CPU,所以任务的大部分时间都在等待IO,CPU利用率低,具有这种特点的任务称为IO密集型任务。

因为存在线程等待的情况,所以在等待的时间,即是是单核cpu,也可以进行线程切换,让其他线程继续用cpu,这样提高了cpu的利用率.

2. 工作线程数是不是设置的越大越好?

案例:

  • 测试设备:AMD r7 4700u , 8核

需求 :求一个亿的随机数据累加的和.

public class T01_MultiVSSingle_ContextSwitch {
    //=====================一亿数据累积求和 ==============================
    private static double[] nums = new double[1_0000_0000];
    private static Random r = new Random();
    private static DecimalFormat df = new DecimalFormat("0.00");

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


    public static void main(String[] args) throws Exception {
        m1();
        m2();
        m3();
    }
}    

单线程方法: m1

   private static void m1() {
        long start = System.currentTimeMillis();

        double result = 0.0;
        for (int i = 0; i < nums.length; i++) {
            result += nums[i];
        }

        long end = System.currentTimeMillis();

        System.out.println("m1: 1个线程" + (end - start) + " result = " + df.format(result));
    }

2个线程 方法: m2

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

    private static void m2() throws Exception {

        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();
        t1.join();
        t2.join();

        result = result1 + result2;

        long end = System.currentTimeMillis();

        System.out.println("m2: 2个线程" + (end - start) + " result = " + df.format(result));
    }

32个线程 方法: m3

 private static void m3() throws Exception {

        final int threadCount = 32;
        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 < nums.length; j++) {
                    results[m] += nums[j];
                }
                latch.countDown();
            });

        }

        double resultM3 = 0.0;

        long start = System.currentTimeMillis();
        for (Thread t : threads) {
            t.start();
        }

        latch.await();
        for (int i = 0; i < results.length; i++) {
            resultM3 += results[i];
        }


        long end = System.currentTimeMillis();

        System.out.println("m3: 32个线程" + (end - start) + " result = " + df.format(result));
    }

测试:

结论:

  • 多线程通常情况下比单线程效率高
  • 线程并不是越多越好,因为线程切换也需要耗费系统资源和时间.

3. 线程池中的线程数量设置多少合适?

根据任务类型推断:

当我们需要初始化一个线程池时,就要考虑我们的线程池被用来执行什么样的任务。

所以我们在设计线程池时,应先对执行的任务有个大体分类,然后根据类型进行设置。一般而言,两种任务的线程数设置如下:

CPU密集型任务:

  • 线程个数为CPU核数。这几个线程可以并行执行,不存在线程切换到开销,提高了cpu的利用率的同时也减少了切换线程导致的性能损耗

IO密集型任务:

  • 线程个数为CPU核数的两倍。到其中的线程在IO操作的时候,其他线程可以继续用cpu,提高了cpu的利用率

合适线程计算公式:

实际的w/c等待时间和计算时间的比率,需要实际生产压测出来.运用相关检测工具.

性能分析工具 profile

不管哪种公式和什么类型的任务,都需要实际生产压测数据为参考.

以上是关于提升--01---线程基础知识的主要内容,如果未能解决你的问题,请参考以下文章

线程学习知识点总结

多线程 Thread 线程同步 synchronized

号称史上最全Java多线程与并发面试题总结—基础篇

几条jQuery代码片段助力Web开发效率提升

PySide 中的多线程提升 Python C++ 代码

十条jQuery代码片段助力Web开发效率提升