java 并发线程个数的如何确定

目录
  • java 并发线程个数的确定
    • cpu密集型
    • io密集型
    • 有锁的情况
  • java 线程池线程数量确定思路
    • 多线程可以快速执行任务的原理
    • 创建线程池需要的参数
    • 确定线程数

java 并发线程个数的确定

本文从控制变量的角度来谈决定线程个数的依据。模型很简单,在实际的生产环境中,情况肯定比下文要复杂的多。要充分的进行测试,以使线程个数为优。

java应用程序大概分为两种:cpu密集型和io密集型。

cpu密集型

就是指线程大部分时间都在用cpu,一般来说,普通的操作都需要用到cpu,比如计算,读取,循环,赋值,查询,排序等等。在最理想的情况下,大牛们建议将线程数设置为count(cpu)+-1

io密集型

io操作一般不需要cpu的参与,线程在io时,线程会被阻塞(线程的六个状态之一就有Blocked)如果一个线程完成某项工作一共需要100ms,其中io需要80ms,cpu需要20ms(忽略其他时间).那么线程数应该设立为5.

有锁的情况

多线程为了安全,往往会加锁。对于关键代码(被频繁调用的代码),往往可以成为线程个数的依据之一。

对于全局锁(比如static上锁),无论多少个线程,代码都是串行执行的。这样线程越多反而越不好。对于锁粒度的越小,对于线程并发来说越有利。比如ConcurrentHashMap来说,分了16个segment,也就是加了16把锁。

在理性的情况下,锁粒度可以降低16倍,那么自然可以允许16个并发。最坏的情况是16个线程去争用一个segment。这个线程的个数需要根据实际情况去调优。

java 线程池线程数量确定思路

多线程可以快速执行任务的原理

因为服务器是拥有多个处理器核心的。运行某进程时,如果只有一个线程,则只能调动一个处理器核心,其他处理器核心可能处于空闲状态。如果是多线程,则可以调用多个处理器核心,用最大效率去处理任务。

创建线程池需要的参数

创建线程池一般需要参数有:核心线程数,最大线程数,线程销毁时间,任务队列,拒绝策略等。

线程池里的线程分为两种,分别是核心线程和非核心线程。当线程池接收到任务时,会先创建核心线程数去处理任务,直至待处理的任务数量超过任务队列长度和核心线程数之和时,会继续创建非核心线程直至最大线程数。

线程池接收到的任务数量在即将超过任务队列长度和最大线程数之和时,会触发拒绝策略处理该任务。

非核心线程在执行完成后会立即销毁,核心线程则会等待设置的销毁时间后再进行销毁。

当任务队列长度足够大时,核心线程数和最大线程数相等,不然不能触发到创建非核心线程

确定线程数

线程数计算公式为:

Nthreads=NcpuUcpu(1+w/c) =Ncpu*(1+w/c)

其中 Nthreads:线程数;Ncpu:处理器核心数;Ucpu:处理器的使用百分比;W/C:等待时间与计算时间的比率

Ncpu可以通过以下代码获取

Runtime.getRuntime().availableProcessors()

等待时间与计算时间的比率

针对IO密集型的,阻塞耗时w一般都是计算耗时几倍c,假设阻塞耗时=计算耗时的情况下,Nthreads=Ncpu*(1+1)=2Ncpu。所以这种情况下,考虑2倍的CPU核心数做为线程数

对于计算密集型的,阻塞耗时趋于0,即w/c趋于0,公式Nthreads = Ncpu。

线程数一般是处理器核心数的整数倍。线程数设置过多,在多任务并发情况下,则会影响服务器的整体运行速度;设置过少,则不能最大化应用服务器性能。所以需要根据具体业务来具体调整。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java并发编程之线程中断

    目录 线程中断: void interrupted()方法:中断线程,例如,当线程A运行时,线程B可以调用线程A的interrupted()方法来设置线程的中断标志为true并立即返回.设置标志仅仅是为了设置标志,线程A实际并没有被中断,它会继续往下执行,如果线程A因为调用了wait()方法,join()方法或者sleep()方法而引起的阻塞挂起,这时候若线程B调用线程A的interrupted()方法,线程A回调用这些方法的地方会抛出InterruptedException异常而返回. boo

  • java高并发的线程中断的几种方式详解

    目录 通过一个变量控制线程中断 通过线程自带的中断标志控制 线程阻塞状态中如何中断? 总结 通过一个变量控制线程中断 代码: package com.itsoku.chat05; import java.util.concurrent.TimeUnit; /** * 微信公众号:路人甲Java,专注于java技术分享(带你玩转 爬虫.分布式事务.异步消息服务.任务调度.分库分表.大数据等),喜欢请关注! */ public class Demo1 { public volatile static

  • java高并发之理解进程和线程

    目录 进程 线程 进程与线程的一个简单解释 总结 进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.程序是指令.数据及其组织形式的描述,进程是程序的实体. 进程具有的特征: 动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的 并发性:任何进程都可以同其他进行一起并发执行 独立性:进程是系统进行资源分配和调度的一个独立单位 结构性:进程由程序,数据和进程控制块三部分组成 我们经常使用wi

  • java高并发之线程的基本操作详解

    目录 新建线程 终止线程 线程中断 等待(wait)和通知(notify) 挂起(suspend)和继续执行(resume)线程 等待线程结束(join)和谦让(yeild) 总结 新建线程 新建线程很简单.只需要使用new关键字创建一个线程对象,然后调用它的start()启动线程即可. Thread thread1 = new Thread1(); t1.start(); 那么线程start()之后,会干什么呢?线程有个run()方法,start()会创建一个新的线程并让这个线程执行run()

  • Java多线程高并发中解决ArrayList与HashSet和HashMap不安全的方案

    1.ArrayList的线程不安全解决方案 将main方法的第一行注释打开,多执行几次,会看到如下图这样的异常信息:

  • java高并发的用户线程和守护线程详解

    目录 程序只有守护线程时,系统会自动退出 设置守护线程,需要在start()方法之前进行 线程daemon的默认值 总结 守护线程是一种特殊的线程,在后台默默地完成一些系统性的服务,比如垃圾回收线程.JIT线程都是守护线程.与之对应的是用户线程,用户线程可以理解为是系统的工作线程,它会完成这个程序需要完成的业务操作.如果用户线程全部结束了,意味着程序需要完成的业务操作已经结束了,系统可以退出了.所以当系统只剩下守护进程的时候,java虚拟机会自动退出. java线程分为用户线程和守护线程,线程的

  • java高并发之线程组详解

    目录 线程组 创建线程关联线程组 为线程组指定父线程组 根线程组 批量停止线程 总结 线程组 我们可以把线程归属到某个线程组中,线程组可以包含多个线程以及线程组,线程和线程组组成了父子关系,是个树形结构,如下图: 使用线程组可以方便管理线程,线程组提供了一些方法方便方便我们管理线程. 创建线程关联线程组 创建线程的时候,可以给线程指定一个线程组,代码如下: package com.itsoku.chat02; import java.util.concurrent.TimeUnit; /** *

  • java 多线程与并发之volatile详解分析

    目录 CPU.内存.缓存的关系 CPU缓存 什么是CPU缓存 为什么要有多级CPU Cache Java内存模型(Java Memory Model,JMM) JMM导致的并发安全问题 可见性 原子性 有序性 volatile volatile特性 volatile 的实现原理 总结 CPU.内存.缓存的关系 要理解JMM,要先从计算机底层开始,下面是一份大佬的研究报告 计算机在做一些我们平时的基本操作时,需要的响应时间是不一样的!如果我们计算一次a+b所需要的的时间: CPU读取内存获得a,1

  • java 并发线程个数的如何确定

    目录 java 并发线程个数的确定 cpu密集型 io密集型 有锁的情况 java 线程池线程数量确定思路 多线程可以快速执行任务的原理 创建线程池需要的参数 确定线程数 java 并发线程个数的确定 本文从控制变量的角度来谈决定线程个数的依据.模型很简单,在实际的生产环境中,情况肯定比下文要复杂的多.要充分的进行测试,以使线程个数为优. java应用程序大概分为两种:cpu密集型和io密集型. cpu密集型 就是指线程大部分时间都在用cpu,一般来说,普通的操作都需要用到cpu,比如计算,读取

  • Java并发线程之线程池的知识总结

    初始化线程池后,把任务丢进去,等待调度就可以了,使用起来比较方便. JAVA中Thread是线程类,不建议直接使用Thread执行任务,在并发数量比较多的情况下,每个线程都是执行一个很短的时间就任务结束了,这样频繁创建线程会大大降低系统的效率,因为频繁的创建和销毁线程需要时间.而线程池可以复用,就是执行完一个任务,并不销毁,而是可以继续执行其它任务. Thread的弊端 每次new Thread() 创建对象,性能差. 线程缺乏统一管理,可能无限制创建线程,相互竞争,有可能占用过多系统资源导致死

  • Java并发 线程间的等待与通知

    前言: 前面讲完了一些并发编程的原理,现在我们要来学习的是线程之间的协作.通俗来说就是,当前线程在某个条件下需要等待,不需要使用太多系统资源.在某个条件下我们需要去唤醒它,分配给它一定的系统资源,让它继续工作.这样能更好的节约资源. 一.Object的wait()与notify() 基本概念: 一个线程因执行目标动作的条件未能满足而被要求暂停就是wait,而一个线程满足执行目标动作的条件之后唤醒被暂停的线程就是notify. 基本模板: synchronized (obj){ //保护条件不成立

  • java并发编程专题(二)----如何创建并运行java线程

    实现线程的两种方式 上一节我们了解了关于线程的一些基本知识,下面我们正式进入多线程的实现环节.实现线程常用的有两种方式,一种是继承Thread类,一种是实现Runnable接口.当然还有第三种方式,那就是通过线程池来生成线程,后面我们还会学习,一步一个脚印打好基础. Runnable接口: public interface Runnable { public abstract void run(); } Thread类: public class Thread implements Runnab

  • Java并发编程之线程之间的共享和协作

    一.线程间的共享 1.1 ynchronized内置锁 用处 Java支持多个线程同时访问一个对象或者对象的成员变量 关键字synchronized可以修饰方法或者以同步块的形式来进行使用 它主要确保多个线程在同一个时刻,只能有一个线程处于方法或者同步块中 它保证了线程对变量访问的可见性和排他性(原子性.可见性.有序性),又称为内置锁机制. 对象锁和类锁 对象锁是用于对象实例方法,或者一个对象实例上的 类锁是用于类的静态方法或者一个类的class对象上的 类的对象实例可以有很多个,但是每个类只有

  • java并发编程JUC CountDownLatch线程同步

    目录 java并发编程JUC CountDownLatch线程同步 1.CountDownLatch是什么? 2.CountDownLatch 如何工作 3.CountDownLatch 代码例子 java并发编程JUC CountDownLatch线程同步 CountDownLatch是一种线程同步辅助工具,它允许一个或多个线程等待其他线程正在执行的一组操作完成.CountDownLatch的概念在java并发编程中非常常见,面试也会经常被问到,所以一定要好好理解掌握. CountDownLa

  • Java并发编程示例(十):线程组

    对线程分组是Java并发API提供的一个有趣功能.我们可以将一组线程看成一个独立单元,并且可以随意操纵线程组中的线程对象.比如,可以控制一组线程来运行同样的任务,无需关心有多少线程还在运行,还可以使用一次中断调用中断所有线程的执行. Java提供了ThreadGroup类来控制一个线程组.一个线程组可以通过线程对象来创建,也可以由其他线程组来创建,生成一个树形结构的线程. 根据<Effective Java>的说明,不再建议使用ThreadGroup.建议使用Executor. --D瓜哥特此

  • Java并发编程示例(九):本地线程变量的使用

    共享数据是并发程序最关键的特性之一.对于无论是继承Thread类的对象,还是实现Runnable接口的对象,这都是一个非常周重要的方面. 如果创建了一个实现Runnable接口的类的对象,并使用该对象启动了一系列的线程,则所有这些线程共享相同的属性.换句话说,如果一个线程修改了一个属性,则其余所有线程都会受此改变的影响. 有时,我们更希望能在线程内单独使用,而不和其他使用同一对象启动的线程共享.Java并发接口提供了一种很清晰的机制来满足此需求,该机制称为本地线程变量.该机制的性能也非常可观.

  • Java并发编程示例(五):线程休眠与恢复

    有时,我们需要在指定的时间点中断正在执行的线程.比如,每分钟检查一次传感器状态的线程,其余时间,线程不需要做任何事情.在此期间,线程不需要使用计算机的任何资源.过了这段时间之后,并且当Java虚拟机调度了该线程,则该线程继续执行.为此,你可以使用Thread类的sleeep()方法.该方法以休眠的方式来推迟线程的执行,而且整数类型的参数则指明休眠的毫秒数.当调用sleep()方法,休眠时间结束后,Java虚拟机分配给线程CPU运行时间,线程就会继续执行. 另一种是用sleep()方法的方式是通过

  • 深入解析Java并发程序中线程的同步与线程锁的使用

    synchronized关键字 synchronized,我们谓之锁,主要用来给方法.代码块加锁.当某个方法或者代码块使用synchronized时,那么在同一时刻至多仅有有一个线程在执行该段代码.当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段.但是,其余线程是可以访问该对象中的非加锁代码块的. synchronized主要包括两种方法:synchronized 方法.synchronized 块. synchron

随机推荐