最近在看《Java虚拟机并发编程》,在此记录一些重要的东东。

线程数的确定:
1. 获取系统可用的处理器核心数:int numOfCores = Runtime.getRuntime().availableProcessors()
2. 如果任务是计算密集型的,则线程数 = numOfCores
        如果任务是IO密集型的,则线程数 = numOfCores / (1 - 阻塞系数), 其中阻塞系数在0~1之间。
注:如果任务被阻塞的时间大于执行时间, 则这些任务是IO密集型的,我们就需要创建比处理器核心数大几倍数量的线程

在解决问题的过程中使处理器一直保持忙碌状态比将负载均摊到每个子任务要实惠得多。
任务完成并不代表线程消亡。

计算密集型任务:如求1到10000000内所有素数的个数

1. AbstractPrimeFinder

public abstract class AbstractPrimeFinder {

    public boolean isPrime(final int number){
if(number <= 1) return false; for(int i = 2; i <=Math.sqrt(number); i++){
if (number % i == 0)
return false;
}
return true;
} public int countPrimesInRange(final int lower, final int upper){
int total = 0;
for( int i = lower; i <= upper; i++){
if(isPrime(i))
total++;
}
return total;
} public void timeAndComputer(final int number){
long start = System.nanoTime();
int numberOfPrimes = countPrimes(number);
long end = System.nanoTime(); System.out.printf("Number of primes under %d is %d\n", number, numberOfPrimes);
System.out.println("Spend time(seconds) is " + (end-start)/1.0e9);
} public abstract int countPrimes(final int number);
}

2. ConcurrentPrimeFinder

/**
* 对于计算密集型的任务,增加线程数并没有什么意义,线程数应该等于CPU内核数。如果较难把任务均摊到CPU,则
* 可以把任务切分成较多块,以确保CPU完成某块任务后,可以继续处理其它块。防止某个CPU完成任务后处于空闲状态。
* @author shj
*
*/
public class ConcurrentPrimeFinder extends AbstractPrimeFinder{
private final int poolSize;
private final int numberOfParts; public ConcurrentPrimeFinder(int poolSize, int numberOfParts){
this.poolSize = poolSize;
this.numberOfParts = numberOfParts;
} @Override
public int countPrimes(final int number) {
int count = 0 ;
try{
List<Callable<Integer>> partitions = new ArrayList<>();
int chunksPerPartition = number / numberOfParts;
for(int i = 0; i < numberOfParts; i++){
final int lower = (i * chunksPerPartition) + 1;
final int upper = (i == numberOfParts - 1) ? number : lower + chunksPerPartition - 1;
partitions.add(new Callable<Integer>(){
public Integer call(){
return countPrimesInRange(lower, upper);
}
});
} ExecutorService executorPool = Executors.newFixedThreadPool(poolSize);
List<Future<Integer>> results = executorPool.invokeAll(partitions, 10000, TimeUnit.SECONDS);
executorPool.shutdown(); for(Future<Integer> result : results){
count += result.get();
}
}catch(Exception e){
e.printStackTrace();
}
return count;
} public static void main(String[] args){
int cores = Runtime.getRuntime().availableProcessors();
int numberOfParts = 20; //划分成子区间的数量, 修改此值查看运行时间的变化
new ConcurrentPrimeFinder(cores,numberOfParts).timeAndComputer(10_000_000);
}
}

java 多线程学习笔记(一) -- 计算密集型任务的更多相关文章

  1. Java多线程学习笔记(一)——多线程实现和安全问题

    1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...

  2. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  3. JAVA多线程学习笔记(1)

    JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...

  4. Java多线程学习笔记

    进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...

  5. Java多线程学习笔记--生产消费者模式

    实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...

  6. java 多线程学习笔记

    这篇文章主要是个人的学习笔记,是以例子来驱动的,加深自己对多线程的理解. 一:实现多线程的两种方法 1.继承Thread class MyThread1 extends Thread{ public ...

  7. Java 多线程学习笔记:生产者消费者问题

    前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...

  8. java多线程学习笔记(三)

    java多线程下的对象及变量的并发访问 上一节讲到,并发访问的时候,因为是多线程,变量如果不加锁的话,会出现“脏读”的现象,这个时候需要“临界区”的出现去解决多线程的安全的并发访问.(这个“脏读”的现 ...

  9. Java多线程学习笔记(一)

    一 概述 一个进程只有一个至少会运行一个线程,Java中同样存在这样,在调用main方法的时候,线程又JVM所创建. package link.summer7c.test; public class ...

随机推荐

  1. 实现两个窗口通信方法-postMessage

    此方案可解决跨域而且跨Iframe,而且http和https之间的交互 首先来看一下基本的语法 otherWindow.postMessage(message, targetOrigin, [tran ...

  2. Smooks:xml-to-java

    引言: Smooks是一个开源的Java框架,用于处理“数据事件流”.它常常被认为是一个转换框架并以此被用于好几个产品和项目中,包括JBoss ESB(以及其它ESB).然而究其核心,Smooks未提 ...

  3. 分享几个高效编写JS 的心得

    原则 不要做任何优化除非的确需要优化   任何的性能优化都必须以测量数据为基础,如果你怀疑代码存在性能问题,首先通过测试来验证你的想法.性能优化三问 我还能做哪些工作从而让代码变得更有效率? 流行的J ...

  4. luogu2627 修剪草坪

    dp[i]表示1~i最大效率 记一下前缀和 转移就是f[i]=max(f[i],f[j-1]-sum[j])+sum[i] (i-k<=j<=i) 发现括号里的只与j有关 开一个单调队列维 ...

  5. 【LeetCode】001. Two Sum

    题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...

  6. Swift中数组和字典都是值类型

    在 Swift 中,所有的基本类型:整数(Integer).浮点数(floating-point).布尔值(Boolean).字符串(string).数组(array)和字典(dictionary), ...

  7. BZOJ1707:[Usaco2007 Nov]tanning分配防晒霜

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  8. js强加方法

    (function () { Array.prototype.removeItem=function (item) { var index=this.indexOf(item); if(index!= ...

  9. 问题:C# params类型参数;结果:C#的参数类型:params、out和ref

    C#的参数类型:params.out和ref PS:由于水平有限,难免会有错误和遗漏,欢迎各位看官批评和指正,谢谢~ 首先回顾一下C#声明一个方法的语法和各项元素,[]代表可选 [访问修饰符] 返回值 ...

  10. 问题:ExecuteNonQuery 与 ExecuteScalar 结果: ExecuteNonQuery方法和ExecuteScalar方法的区别

    ExecuteNonQuery方法和ExecuteScalar方法的区别 ----ExecuteNonQuery():执行命令对象的SQL语句,返回一个int类型变量,如果SQL语句是对数据库的记录进 ...