电脑多线程有什么用 解析电脑多线程用处和应用

摘要线程可以被认为是操作系统可以调度的最小程序执行序列。通常,作为一个进程的组成部分,同一个进程中的多个线程可以共享资源(如内存等。)的流程。JVM线程和内核轻量级进程是一对一的映射关系,所以JVM中的线程是非常有价值的。工程上多线程的实现一般都是基于线程池的。因...

摘要

线程可以被认为是操作系统可以调度的最小程序执行序列。通常,作为一个进程的组成部分,同一个进程中的多个线程可以共享资源(如内存等。)的流程。JVM线程和内核轻量级进程是一对一的映射关系,所以JVM中的线程是非常有价值的。

工程上多线程的实现一般都是基于线程池的。因为与自己创建线程相比,多线程具有以下优势

线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。

遗嘱执行人怎么了?

看阿里巴巴的并发编程开发手册。有一个规则:线程池不允许使用Executors创建,而是通过ThreadPoolExecutor的方式创建。

为什么遗嘱执行人有瑕疵?

1.线程池的工作原理

当任务希望通过execute(Runnable)方法添加到线程池时:

如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于***ximumPoolSize,建新的线程来处理被添加的任务。那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程***ximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态地调整池中的线程数。

2.newFixedThreadPool分析

Java中BlockingQueue的实现主要有两种,即ArrayBlockingQueue和LinkedBlockingQueue。

ArrayBlockingQueue是由array实现的有界阻塞队列,其容量必须设置。

LinkedBlockingQueue是由链表实现的有界阻塞队列,其容量可以任意设置。如果没有设置,它将是一个无边界的阻塞队列,最大长度为整数。最大值

问题来了:如果不设置,将是一个无边界阻塞队列,最大长度为整数。MAX_VALUE也就是说,如果我们不设置LinkedBlockingQueue的容量,那么它的默认容量将是整数。最大值

但是,在newFixedThreadPool中创建LinkedBlockingQueue时,未指定容量。此时,LinkedBlockingQueue是一个无边界队列。对于无边界队列,您可以不断地向队列中添加任务。在这种情况下,过多的任务可能会导致内存溢出。

3.newCachedThreadPool分析

结合上面的流程图,核心线程数=0,最大线程数无限大,因为SynchronousQueue是一个阻塞队列,缓存值为1。当有大量任务请求时,线程池会创建大量线程,导致OOM。

线程池参数的详细说明

1.施工方法

/** * @param corePoolSize 核心线程数 * @param ***ximumPoolSize 最大线程数 * @param keepAliveTime 线程所允许的空闲时间 * @param unit 线程所允许的空闲时间的单位 * @param workQueue 线程池所使用的缓冲队列 * @param handler 线程池对拒绝任务的处理策略 */ThreadPoolExecutor(int corePoolSize, int ***ximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable>workQueue, RejectedExecutionHandler handler)

2.线程池拒绝策略

RejectedExecutionHandler(saturation strategy):当队列和线程池都满了,就意味着线程池饱和了,那么必须采取一种策略来处理提交的新任务。默认情况下,该策略为AbortPolicy,这意味着当无法处理新任务时会引发异常。。以下是JDK1.5提供的四种策略。

AbortPolicy:直接抛出异常CallerRunsPolicy:只用调用者所在线程来运行任务。DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。DiscardPolicy:不处理,丢弃掉。当然也可以根据应用场景需要来实现RejectedExecutionHandler接口自定义策略。如记录日志或持久化不能处理的任务。

打开线程池的正确方法

1.创建线程池

避免使用Executors创建线程池,主要是避免使用默认实现,所以我们可以直接调用ThreadPoolExecutor的构造函数自己创建线程池。在创建的同时,指定BlockQueue的容量就足够了。

ThreadPoolExecutor executorService = new ThreadPoolExecutor(8, 16, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(10));

2.将任务提交给线程池

我们可以使用execute提交的任务,但是execute方法没有返回值,所以无法判断任务是否被线程池成功执行。下面的代码显示了由execute方法输入的任务是Runnable类的一个实例。

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>(60)); threadPoolExecutor.execute(new Runnable() { @Override public void run() { System.out.println("线程池无返回结果"); } });

我们也可以用submit方法提交一个任务,这个任务会返回一个future,那么我们就可以通过这个future来判断任务是否执行成功,通过future的get方法得到返回值。get方法将阻塞任务直到它完成,而get(long timeout,TimeUnit unit)方法将阻塞它一段时间,然后立即返回。这个时候,任务可能还没完成。

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20, 5, TimeUnit.SECONDS, new LinkedBlockingDeque<>(60)); Future<String>future = threadPoolExecutor.submit(new Callable<String>() { @Override public String call() throws Exception { return "ok"; } }); System.out.println("线程池返回结果:" + future.get());

3.关闭线程池

shutdown关闭线程池

方法定义:public void shutdown()

(1)线程池的状态变为SHUTDOWN,此时不能向线程池添加新的任务,否则会抛出
rejectedexecutionexception异常。

(2)线程池不会立即退出,直到添加到线程池的所有任务都已被处理。

请注意,该函数不会等待提交的任务完成。要等待所有任务完成,您可以调用:

公共布尔awaitTermination(longtimeout,TimeUnit单位)

shut down现在关闭线程池并中断任务

方法定义:公共列表shutdownNow()

(1)线程池的状态立即变为停止状态,此时不能向线程池添加新的任务。

(2)终止等待执行的线程并返回它们的列表;

(3)尝试停止所有正在执行的线程。终止的方法是调用Thread.interrupt()。但众所周知,如果线程中没有睡眠、等待、条件、定时锁等应用,interrupt()方法是无法中断当前线程的。所以ShutdownNow()并不意味着线程池可以马上退出。它可能必须等待所有正在执行的任务完成后才能退出。

4.如何配置线程池大小

CPU密集型任务

这个任务需要大量的运算,不存在拥塞。CPU总是全速运行。只有在真正的多核CPU上,才能通过多线程来加速CPU密集型任务。配置尽可能少的线程:

CPU数量+1个线程的线程池。

比如:CPU 16核,内存32G。线程数=16

IO密集型任务

如果IO密集型任务线程并不总是执行任务,您应该配置尽可能多的线程,例如CPU内核*2。

当一个大工厂设置了IO密集型的策略时,大多数线程都被阻塞了,所以有必要配置更多的线程:

CPU内核数量/(1-阻塞系数)

例子:CPU 16核,阻塞系数0.9 ————->16/(1-0.9) = 160个线程。

这时,非阻塞线程=16

本文来自至尊狂魔┈投稿,不代表舒华文档立场,如若转载,请注明出处:https://www.chinashuhua.cn/24/628482.html

打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
() 0
上一篇 07-10
下一篇 07-10

相关推荐

  • 线程撕裂者1920X评测跑分参数介绍

    XE好,再看下这两款处理器的具体参数锐龙ThreadRipper 3990X,核心架构Zen 2,制造工艺nm 7nm,核心线程64128,核心频率GHz 29 ,加速频率GHz4。1线程撕裂者3990X这款cpu是当今世上最强的cpu没有之一,强大的可以让你的电脑如飞一般,不用担心任何不够用的问题2线程撕裂者397

    2023-07-29 07:53:01
    491 0
  • 线程撕裂者2990WX详细参数评测

    1、而酷睿i99980XE的竞争对手是第二代线程撕裂者29902990拥有32核心64线程,基础频率30GHz,睿频最以加速到42GHz,制造工艺是12nm从基本参数上来看2990不管是制造工艺还是核心数量都领先于英特尔的酷睿i99980X。2、左右 通过主要参数对比我们发现AMD 2990线程撕裂者处理器是3

    2023-07-21 09:53:01
    656 0
  • 线程间的通信方式有哪些 qt信号槽机制的实现原理

    一:什么时候需要沟通1.当多个线程并发执行时,默认情况下,CPU会随机切换线程。2.如果我们希望它们定期执行,我们可以使用通信,比如每个线程一次。3、等待():使当前线程挂起并放弃CPU,同步资源,以便其他线程访问和修改共享资源,而当前线程正在排队等待再次访问资源。如果

    2023-07-18 12:36:01
    286 0
  • 远程线程注入什么意思 远程线程注入案例

    译者:myswsun预计稿费:300元提交方式:发送邮件至林微#360.cn,或登录网页在线提交。0x00前言进程注入是恶意软件和无文件攻击中广泛使用的一种规避技术,这意味着自定义代码可以在另一个进程的地址空中运行。进程注入提高了隐蔽性,也实现了持久性。虽然进程注入技术有很多,但

    2023-07-15 15:17:01
    187 0

评论列表

联系我们

在线咨询: QQ交谈

邮件:admin@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信