C#开发的人脸左右相似度计算软件源码分析

本文实例讲述了C#开发的人脸左右相似度计算软件。分享给大家供大家参考。具体分析如下:

模仿湖南卫视快乐大本营中所使用的一款人脸左右对称相似度计算软件,自己写的一个小软件,使用语言是C#,希望跟喜欢这个软件的同志们共享!

1. FaceClass类程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace FaceSmile
{
 class FaceClass
 {
  /// <summary>
  /// 左脸对称函数
  /// </summary>
  /// <param name="a"></param>
  /// <returns></returns>
  public static Bitmap FaceFlipLeft(Bitmap a)
  {
   Rectangle rect = new Rectangle(0, 0, a.Width, a.Height);
   System.Drawing.Imaging.BitmapData srcData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, a.PixelFormat);
   IntPtr ptr = srcData.Scan0;
   int bytes = 0;
   bytes = srcData.Stride * a.Height;
   byte[] grayValues = new byte[bytes];
   System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
   byte[] temp = new byte[bytes];
   temp = (byte[])grayValues.Clone();
   for (int j = 0; j < a.Height; j++)
   {
    for (int i = 0; i < (int)(a.Width/2); i++)
    {
     temp[(a.Width - 2 - i) * 3 + j * srcData.Stride] = temp[i * 3 + j * srcData.Stride];
     temp[(a.Width - 2 - i) * 3 + 1 + j * srcData.Stride] = temp[i * 3 + 1 + j * srcData.Stride];
     temp[(a.Width - 2 - i) * 3 + 2 + j * srcData.Stride] = temp[i * 3 + 2 + j * srcData.Stride];
    }
   }
   grayValues = (byte[])temp.Clone();
    System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
   a.UnlockBits(srcData);
   return a;
  }
  /// <summary>
  /// 右脸对称函数
  /// </summary>
  /// <param name="a"></param>
  /// <returns></returns>
  public static Bitmap FaceFlipRight(Bitmap a)
  {
   Rectangle rect = new Rectangle(0, 0, a.Width, a.Height);
   System.Drawing.Imaging.BitmapData srcData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, a.PixelFormat);
   IntPtr ptr = srcData.Scan0;
   int bytes = 0;
   bytes = srcData.Stride * a.Height;
   byte[] grayValues = new byte[bytes];
   System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
   byte[] temp = new byte[bytes];
   temp = (byte[])grayValues.Clone();
   for (int j = 0; j < a.Height; j++)
   {
    for (int i = 0; i < (int)(a.Width / 2); i++)
    {
     temp[i * 3 + j * srcData.Stride] = temp[(a.Width - 2 - i) * 3 + j * srcData.Stride];
     temp[i * 3 + 1 + j * srcData.Stride] = temp[(a.Width - 2 - i) * 3 + 1 + j * srcData.Stride];
     temp[i * 3 + 2 + j * srcData.Stride] = temp[(a.Width - 2 - i) * 3 + 2 + j * srcData.Stride];
    }
   }
   grayValues = (byte[])temp.Clone();
   System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
   a.UnlockBits(srcData);
   return a;
  }
  /// <summary>
  /// 定义肤色检测函数
  /// </summary>
  /// <param name="a"></param>
  /// <returns></returns>
  public static Bitmap SkinDetect(Bitmap a)
  {
   Rectangle rect = new Rectangle(0, 0, a.Width, a.Height);
   System.Drawing.Imaging.BitmapData bmpData = a.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
   int stride = bmpData.Stride;
   unsafe
   {
    byte* pIn = (byte*)bmpData.Scan0.ToPointer();
    byte* P;
    int R, G, B;
    double r, g, Fupr, Flor, Wrg;
    for (int y = 0; y < a.Height; y++)
    {
     for (int x = 0; x < a.Width; x++)
     {
      P = pIn;
      B = P[0];
      G = P[1];
      R = P[2];
      if (R + G + B == 0)
      {
       r = 0;
       g = 0;
      }
      else
      {
       r = (R / (R + G + B));
       g = (G / (R + G + B));
      }
      Fupr = (1.0743 * r + 0.1452 - 1.3767 * r * r);
      Flor = (0.5601 * r + 0.1766 - 0.776 * r * r);
      Wrg = (r - 0.33) * (r - 0.33) + (g - 0.33) * (g - 0.33);
      if ((R - G >= 45) && ((R > G) && (G > B)) && (Fupr > g) && (Wrg >= 0.0004))
      {
       P[0] = (byte)B;
       P[1] = (byte)G;
       P[2] = (byte)R;
      }
      else
      {
       P[0] = 0;
       P[1] = 0;
       P[2] = 0;
      }
      pIn += 3;
     }
     pIn += stride - a.Width * 3;
    }
   }
   a.UnlockBits(bmpData);
   return a;
  }
  /// <summary>
  /// 定义图像灰度化函数
  /// </summary>
  /// <param name="src"></param>
  /// <returns></returns>
  public static Bitmap ImageGray(Bitmap src)
  {
   int w = src.Width;
   int h = src.Height;
   //构建与原图像大小一样的模版图像
   Bitmap dstBitmap = new Bitmap(src.Width, src.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
   //将原图像存入内存
   System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
   System.Drawing.Imaging.BitmapData dstData = dstBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
   unsafe
   {
    byte* pIn = (byte*)srcData.Scan0.ToPointer();
    byte* pOut = (byte*)dstData.Scan0.ToPointer();
    byte* p;
    int stride = srcData.Stride;
    int r, g, b;
    for (int y = 0; y < h; y++)
    {
     for (int x = 0; x < w; x++)
     {
      p = pIn;
      r = p[2];
      g = p[1];
      b = p[0];
      //调用图像灰度化公式
      pOut[0] = pOut[1] = pOut[2] = (byte)(b * 0.114 + g * 0.587 + r * 0.299);
      pIn += 3;
      pOut += 3;
     }
     pIn += srcData.Stride - w * 3;
     pOut += srcData.Stride - w * 3;
    }
    src.UnlockBits(srcData);
    dstBitmap.UnlockBits(dstData);
    return dstBitmap;
   }
  }
 }
}

2. SameRatioClass类程序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace FaceSmile
{
 class SameRatioClass
 {
  /// <summary>
  /// 左右脸相似度函数
  /// </summary>
  /// <param name="src"></param>
  /// <param name="dst"></param>
  /// <returns></returns>
  public static double SameRatio(Bitmap src, Bitmap dst)
  {
   byte[] srcData = GetBytes(src);
   byte[] dstData = GetBytes(dst);
   double ratio = 0;
   int sum = 0;
   int std=0;
   for (int i = 0; i < srcData.Length; i++)
   {
    sum += Math.Abs(srcData[i] - dstData[i]);
    std += srcData[i];
   }
   ratio = 100-(double)(100*sum / std);
   return ratio;
  }
  /// <summary>
  /// 得到图像信息函数
  /// </summary>
  /// <param name="src"></param>
  /// <returns></returns>
  private static byte[] GetBytes(Bitmap src)
  {
   int w = src.Width;
   int h = src.Height;
   byte[] dataImage = new byte[w * h];
   System.Drawing.Imaging.BitmapData srcData = src.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
   unsafe
   {
    byte* pIn = (byte*)srcData.Scan0.ToPointer();
    byte* p;
    int stride = srcData.Stride;
    int r, g, b;
    for (int y = 0; y < h; y++)
    {
     for (int x = 0; x < w; x++)
     {
      p = pIn;
      r = p[2];
      g = p[1];
      b = p[0];
      dataImage[x + y * x] = (byte)((r + g + b) / 3);
      pIn += 3;
     }
     pIn += srcData.Stride - w * 3;
    }
    src.UnlockBits(srcData);
    return dataImage;
   }
  }
 }
}

3. 主窗体程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace FaceSmile
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
   groupBox1.Visible = true;
   groupBox2.Visible = false;
  }
  #region 全局变量定义
  //定义原始图像变量
  private Bitmap src ;
  //定义图像相似度变量
  private double ratio = 0;
  //定义图像路径变量
  private string curFileName;
  //定义人脸位置图像调整变量
  private int numAdjust = 0;
  #endregion
  #region 软件操作
  //左脸对称
  private void button1_Click(object sender, EventArgs e)
  {
   if (src != null)
   {
    Bitmap temp = (Bitmap)src.Clone();
    Bitmap a = FaceClass.FaceFlipLeft(temp);
    pictureBox1.Image = (Image)a;
    ratio = SameRatioClass.SameRatio(a, src);
    label1.Text = ratio.ToString();
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  //右脸对称
  private void button2_Click(object sender, EventArgs e)
  {
   if (src != null)
   {
    Bitmap temp = (Bitmap)src.Clone();
    Bitmap a = FaceClass.FaceFlipRight(temp);
    pictureBox1.Image = (Image)a;
    ratio = SameRatioClass.SameRatio(a, src);
    label1.Text = ratio.ToString();
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  //打开图像
  private void button3_Click(object sender, EventArgs e)
  {
   OpenImage();
   if (src != null)
   {
    pictureBox1.Image = (Image)src;
    pictureBox1.Width = src.Width;
    pictureBox1.Height = src.Height;
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  //保存图像
  private void button4_Click(object sender, EventArgs e)
  {
   SaveImage();
  }
  //图像打开函数
  private void OpenImage()
  {
   try
   {
    ofd.Filter = "All files (*.*)|*.*|bmp files (*.bmp)|*.bmp|jpeg files (*.jpg)|*.jpg|png files (*.png)|*.png";
    ofd.Title = "打开";
    ofd.ShowHelp = true;
    if (ofd.ShowDialog() == DialogResult.OK)
    {
     curFileName = ofd.FileName;
     src = new Bitmap(curFileName);
    }
   }
   catch (Exception ex)
   {
    MessageBox.Show(ex.Message);
   }
  }
  //图像保存函数
  private void SaveImage()
  {
   try
   {
    sfd.Filter = "保存(*.bmp)|*.bmp";
    sfd.Title = "保存";
    sfd.ShowHelp = true;
    if (sfd.ShowDialog() == DialogResult.OK)
    {
     Bitmap temp = (Bitmap)pictureBox1.Image;
     temp.Save(sfd.FileName, System.Drawing.Imaging.ImageFormat.Bmp);
    }
   }
   catch (Exception ex)
   {
    MessageBox.Show(ex.Message);
   }
  }
  //其他操作
  private void button5_Click(object sender, EventArgs e)
  {
   groupBox2.Location = new Point(groupBox1.Location.X, groupBox1.Location.Y);
   groupBox2.Visible = true;
   groupBox1.Visible = false;
  }
  //肤色检测
  private void button6_Click(object sender, EventArgs e)
  {
   if (pictureBox1.Image != null)
   {
    pictureBox1.Image = (Image)FaceClass.SkinDetect((Bitmap)pictureBox1.Image);
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  //返回操作
  private void button7_Click(object sender, EventArgs e)
  {
   groupBox1.Visible = true;
   groupBox2.Visible = false;
  }
  //灰度化
  private void button8_Click(object sender, EventArgs e)
  {
   if (pictureBox1.Image != null)
   {
    pictureBox1.Image = (Image)FaceClass.ImageGray((Bitmap)pictureBox1.Image);
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  //博客连接
  private void label2_Click(object sender, EventArgs e)
  {
   System.Diagnostics.Process.Start("IEXPLORE.EXE", "http://dongtingyueh.blog.163.com/");
  }
  //修正人脸位置
  private void button9_Click(object sender, EventArgs e)
  {
   if (numAdjust != 0)
   {
    int a = numAdjust;
    int b = src.Width - a;
    int result = a < b ? a : b;
    if (result == b)
    {
     src = src.Clone(new Rectangle(src.Width - 2 * result, 0, 2 * result, src.Height), src.PixelFormat);
    }
    else
    {
     src = src.Clone(new Rectangle(0, 0, 2 * result, src.Height), src.PixelFormat);
    }
    pictureBox1.Image = (Image)src;
    pictureBox1.Width = src.Width;
    pictureBox1.Height = src.Height;
   }
   trackBar1.Value = 0;
   label4.Text = "0";
  }
  #endregion
  #region 人脸位置修正
  private void trackBar1_Scroll(object sender, EventArgs e)
  {
   if (src != null)
   {
    trackBar1.Maximum = src.Width;
    trackBar1.Minimum = 0;
    numAdjust = trackBar1.Value;
    label4.Text = numAdjust.ToString();
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  private void trackBar1_ValueChanged(object sender, EventArgs e)
  {
   pictureBox1.Invalidate();
  }
  private void trackBar1_MouseUp(object sender, MouseEventArgs e)
  {
   if (src != null)
   {
    Graphics g = pictureBox1.CreateGraphics();
    g.DrawLine(new Pen(Color.Red, 2), new Point((int)(numAdjust), 0), new Point((int)(numAdjust), src.Height));
    g.Dispose();
   }
   else
   {
    MessageBox.Show("Please open one image!");
   }
  }
  #endregion
 }
}

希望本文所述对大家的C#程序设计有所帮助。

(0)

相关推荐

  • C#实现计算一个点围绕另一个点旋转指定弧度后坐标值的方法

    本文实例讲述了C#实现计算一个点围绕另一个点旋转指定弧度后坐标值的方法.分享给大家供大家参考.具体如下: 1.示例图 P(x1,y1)以点A(a,b)为圆心,旋转弧度为θ,求旋转后点Q(x2,y2)的坐标 2.实现方法 先将坐标平移,计算点(x1-a,y1-b)围绕原点旋转后的坐标,再将坐标轴平移到原状态 /// <summary> /// 结构:表示一个点 /// </summary> struct Point { //横.纵坐标 public double x, y; //构造

  • C#计算文件MD5校验的方法

    本文实例讲述了C#计算文件MD5校验的方法.分享给大家供大家参考.具体分析如下: C#计算文件的MD5校验,从互联网上下载一个文件,可以使用下面的代码对文件进行MD5校验,看看生成的MD5编码是否和网站提供的一致,如果不一致则表示文件被修改过了,要慎重. protected string GetMD5HashFromFile(string fileName) { FileStream file = new FileStream(fileName,FileMode.Open); MD5 md5 =

  • C#计算字符串相似性的方法

    本文实例讲述了C#计算字符串相似性的方法.分享给大家供大家参考.具体如下: 计算字符串相似性的办法很多,甚至最笨的办法可以挨个匹配,这里要讲的是使用莱文史特距离来计算字符串相似性. 莱文史特距离概念:假设函数名是LD 用于计算两个字符串之间的相似度. 譬如有两个字符串A和B.假设以A为基准,那么该算法就是计算把B通过(替换.删除.加字符)等方法变成A需要多少步. 例如: A="abcd", B="abc", 那么 LD(A,B)=1,只需在B字符串中插入一个字符那么

  • C#计算字符串哈希值(MD5、SHA)的方法小结

    本文实例讲述了C#计算字符串哈希值(MD5.SHA)的方法.分享给大家供大家参考.具体如下: 一.关于本文 本文中是一个类库,包括下面几个函数: ① 计算32位MD5码(大小写):Hash_MD5_32 ② 计算16位MD5码(大小写):Hash_MD5_16 ③ 计算32位2重MD5码(大小写):Hash_2_MD5_32 ④ 计算16位2重MD5码(大小写):Hash_2_MD5_16 ⑤ 计算SHA-1码(大小写):Hash_SHA_1 ⑥ 计算SHA-256码(大小写):Hash_SHA

  • C#计算程序执行过程花费时间的方法

    本文实例讲述了C#计算程序执行过程花费时间的方法.分享给大家供大家参考.具体如下: 计算执行完程序花费的时间: void AddInfo() { System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); for (int i = 0; i < 1000; i++) { Console.WriteLine(i.ToString()); System.Threading.Thread.Sleep

  • C#图像处理之图像均值方差计算的方法

    本文实例讲述了C#图像处理之图像均值方差计算的方法.分享给大家供大家参考.具体如下: //本函数均是基于RGB颜色空间计算 //定义图像均值函数(RGB空间) public double AnBitmap(Bitmap a) { double V = 0; Rectangle rect = new Rectangle(0, 0, a.Width, a.Height); System.Drawing.Imaging.BitmapData bmpData = a.LockBits(rect, Sys

  • C#实现计算年龄的简单方法汇总

    vs2010测试通过,主要思想是由出生日期和当前日期,两个日期计算出年龄(岁.月.天) using System; using System.Collections.Generic; using System.Text; namespace PublicClass { public static class CalculationDate { /// <summary> /// 由两个日期计算出年龄(岁.月.天) /// </summary> public static void

  • C#编程实现四舍五入、向上及下取整的方法

    本文实例讲述了C#编程实现四舍五入.向上及下取整的方法.分享给大家供大家参考,具体如下: 在处理一些数据时,我们希望能用"四舍五入"法实现,但是C#采用的是"四舍六入五成双"的方法,如下面的例子,就是用"四舍六入五成双"得到的结果: double d1 = Math.Round(1.25, 1);//1.2 double d2 = Math.Round(1.24, 1);//1.2 double d3 = Math.Round(1.26, 1);

  • C#编程实现取整和取余的方法

    本文实例讲述了C#编程实现取整和取余的方法.分享给大家供大家参考,具体如下: "%"为取余号,不用多说. "/"号现在整形运算是取整,浮点运算时为除法运算,如54/10结果为5,54.0/10.0结果为5.4而且取整时不进行四舍五入只取整数部分,如54/10和56/10是5. Math.Celling()取整数的较大数,即向上取整.相当于不管余数是什么都会进一位.如Math.Celling(54.0/10.0)结果为6. Math.Ceiling(Convert.T

  • C#开发的人脸左右相似度计算软件源码分析

    本文实例讲述了C#开发的人脸左右相似度计算软件.分享给大家供大家参考.具体分析如下: 模仿湖南卫视快乐大本营中所使用的一款人脸左右对称相似度计算软件,自己写的一个小软件,使用语言是C#,希望跟喜欢这个软件的同志们共享! 1. FaceClass类程序 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Dra

  • python opencv人脸识别考勤系统的完整源码

    如需安装运行环境或远程调试,可加QQ905733049, 或QQ2945218359由专业技术人员远程协助! 运行结果如下: 代码如下: import wx import wx.grid from time import localtime,strftime import os import io import zlib import dlib # 人脸识别的库dlib import numpy as np # 数据处理的库numpy import cv2 # 图像处理的库OpenCv impo

  • 论文查重python文本相似性计算simhash源码

    场景: 1.计算SimHash值,及Hamming距离.2.SimHash适用于较长文本(大于三五百字)的相似性比较,文本越短误判率越高. Python实现: 代码如下 # -*- encoding:utf-8 -*- import math import jieba import jieba.analyse class SimHash(object): def getBinStr(self, source): if source == "": return 0 else: x = o

  • Android开发Retrofit源码分析

    目录 项目结构 retrofit 使用 Retrofit #create ServiceMethod #parseAnnotations HttpServiceMethod#parseAnnotations 第二种 非Kotlin协程情况 DefaultCallAdapterFactory#get 第一种 Kotlin协程情况 总结 项目结构 把源码 clone 下来 , 可以看到 retrofit 整体结构如下 图 http包目录下就是一些http协议常用接口 , 比如 请求方法 url ,

  • rollup cli开发全面系统性rollup源码分析

    目录 引言 prefix symlink Executables(可执行文件) rollup 命令行的开发 打包生成 rollup 文件 引言 在学习 rollup CLI 之前我们需要了解 npm 中的 prefix,symlink,Executables 这三个概念. prefix 当我们使用 --global/-g 选项的时候会将包安装到 prefix 目录下,prefix 默认为 node 的安装位置.在大多数系统上,它是 /usr/local. 在 Windows 上,它是 %AppD

  • asp.net开发中常见公共捕获异常方式总结(附源码)

    本文实例总结了asp.net开发中常见公共捕获异常方式.分享给大家供大家参考,具体如下: 前言:在实际开发过程中,对于一个应用系统来说,应该有自己的一套成熟的异常处理框架,这样当异常发生时,也能得到统一的处理风格,将异常信息优雅地反馈给开发人员和用户.我们都知道,.net的异常处理是按照"异常链"的方式从底层向高层逐层抛出,如果不能尽可能地早判断异常发生的边界并捕获异常,CLR会自动帮我们处理,但是这样系统的开销是非常大的,所以异常处理的一个重要原则是"早发现早抛出早处理&q

  • Android仿zaker用手向上推动的特效开发【推动门效果】(附demo源码下载)

    本文实例讲述了Android仿zaker用手向上推动的特效开发.分享给大家供大家参考,具体如下: 最近在商店下载了zaker ,闲暇时拿来看看新闻!发现每次打开软件进入主界面时有个界面,需要你把它往上滑到一定距离才能进入到主界面.每次进入软件时它的背景可能不一样,在往上拨的时候你会看见主界面,好似向上推的门一样!打开它你就可以看到外面的世界.与窗帘有点不同的是在你没有拉开足够距离时,它会俏皮的关闭自己不让你看到外面的美景. 说这么多想像起来挺模糊的,那让我们看看实际效果图,我现在打开zaker截

  • 微信公众平台开发-微信服务器IP接口实例(含源码)

    学习了access_token的获取及应用后,正式的使用access_token调用下其他微信公众平台的接口,加深认识与使用方法. 一.获取微信服务器IP地址实例 (一)接口介绍 如果公众号基于安全等考虑,需要获知微信服务器的IP地址列表,以便进行相关限制,可以通过该接口获得微信服务器IP地址列表或者IP网段信息. (二)实例调用 接口说明 http请求方式:GET 接口调用地址: https://api.weixin.qq.com/cgi-bin/getcallbackip?access_to

  • 关于PHP的相似度计算函数:levenshtein的使用介绍

    使用说明先看手册上 levenshtein() 函数的说明: levenshtein() 函数返回两个字符串之间的 Levenshtein 距离. Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符. 例如把 kitten 转换为 sitting: sitten (k→s)sittin (e→i)sitting (→g)levenshtein() 函数给每个操作(替换

  • Android开发中线程池源码解析

    线程池(英语:thread pool):一种线程使用模式.线程过多会带来调度开销,进而影响缓存局部性和整体性能.而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务.这避免了在处理短时间任务时创建与销毁线程的代价.线程池不仅能够保证内核的充分利用,还能防止过分调度.可用线程数量应该取决于可用的并发处理器.处理器内核.内存.网络sockets等的数量. 例如,线程数一般取cpu数量+2比较合适,线程数过多会导致额外的线程切换开销.----摘自维基百科 我们在Android或者Java开发中

随机推荐