文档库 最新最全的文档下载
当前位置:文档库 › C++的SHA-1实现

C++的SHA-1实现

C++的SHA-1实现
C++的SHA-1实现

基于C/C++的SHA-1算法实现,可实现对字符串的SHA-1计算

在VC++ 6.0下编译通过

运行截图如下:

包含四个文件,其中sha1test.cpp为main()所在文件,其余三个文件皆为sha-1算法实现。备注:sha1.h,stdint.h,sha1.cpp皆为引用它人源程序或Openssl标准库,非本人原创。sha1test.cpp为本人修改程序

1、sha1.h

#ifndef _SHA1_H_

#define _SHA1_H_

#include "stdint.h"

#ifndef _SHA_enum_

#define _SHA_enum_

enum

{

shaSuccess = 0,

shaNull, /* 空指示参量*/

shaInputTooLong, /* 输入数据太长提示*/

shaStateError /* called Input after Result --以输入结果命名之*/

};

#endif

#define SHA1HashSize 20

/*

* 以下这种结构将会控制上下文消息for the SHA-1

* hashing operation

*/

typedef struct SHA1Context

{

uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */

uint32_t Length_Low; /* Message length in bits */

uint32_t Length_High; /* Message length in bits */

/* Index into message block array */

int_least16_t Message_Block_Index;

uint8_t Message_Block[64]; /* 512-bit message blocks */

int Computed; /* Is the digest computed? */

int Corrupted; /* Is the message digest corrupted? */

} SHA1Context;

/*

* 函数原型

*/

int SHA1Reset( SHA1Context *);

int SHA1Input( SHA1Context *,

const uint8_t *,

unsigned int);

int SHA1Result( SHA1Context *,

uint8_t Message_Digest[SHA1HashSize]);

#endif /*_SHA1_H_*/

2、stdint.h

/* ISO C9x 7.18 Integer types

* Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)

*

* THIS SOFTWARE IS NOT COPYRIGHTED

*

* Contributor: Danny Smith

*

* This source code is offered for use in the public domain. You may

* use, modify or distribute it freely.

*

* This code is distributed in the hope that it will be useful but

* WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY

* DISCLAIMED. This includes but is not limited to warranties of

* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*

* Date: 2000-12-02

*/

#ifndef _STDINT_H

#define _STDINT_H

#define __need_wint_t

#define __need_wchar_t

#include

/* 7.18.1.1 Exact-width integer types */

typedef signed char int8_t;

typedef unsigned char uint8_t;

typedef short int16_t;

typedef unsigned short uint16_t;

typedef int int32_t;

typedef unsigned uint32_t;

typedef long int64_t;

typedef unsigned long uint64_t;

/* 7.18.1.2 Minimum-width integer types */

typedef signed char int_least8_t;

typedef unsigned char uint_least8_t;

typedef short int_least16_t;

typedef unsigned short uint_least16_t;

typedef int int_least32_t;

typedef unsigned uint_least32_t;

typedef long int_least64_t;

typedef unsigned long uint_least64_t;

/* 7.18.1.3 Fastest minimum-width integer types

* Not actually guaranteed to be fastest for all purposes

* Here we use the exact-width types for 8 and 16-bit ints. */

typedef char int_fast8_t;

typedef unsigned char uint_fast8_t;

typedef short int_fast16_t;

typedef unsigned short uint_fast16_t;

typedef int int_fast32_t;

typedef unsigned int uint_fast32_t;

typedef long int_fast64_t;

typedef unsigned long uint_fast64_t;

/* 7.18.1.4 Integer types capable of holding object pointers */ typedef int intptr_t;

typedef unsigned uintptr_t;

/* 7.18.1.5 Greatest-width integer types */

typedef long intmax_t;

typedef unsigned long uintmax_t;

/* 7.18.2 Limits of specified-width integer types */

#if !defined ( __cplusplus) || defined (__STDC_LIMIT_MACROS)

/* 7.18.2.1 Limits of exact-width integer types */

#define INT8_MIN (-128)

#define INT16_MIN (-32768)

#define INT32_MIN (-2147483647 - 1)

#define INT64_MIN (-9223372036854775807LL - 1)

#define INT8_MAX 127

#define INT16_MAX 32767

#define INT32_MAX 2147483647

#define INT64_MAX 9223372036854775807LL

#define UINT8_MAX 0xff /* 255U */

#define UINT16_MAX 0xffff /* 65535U */

#define UINT32_MAX 0xffffffff /* 4294967295U */

#define UINT64_MAX 0xffffffffffffffffULL /* 18446744073709551615ULL */

/* 7.18.2.2 Limits of minimum-width integer types */

#define INT_LEAST8_MIN INT8_MIN

#define INT_LEAST16_MIN INT16_MIN

#define INT_LEAST32_MIN INT32_MIN

#define INT_LEAST64_MIN INT64_MIN

#define INT_LEAST8_MAX INT8_MAX

#define INT_LEAST16_MAX INT16_MAX

#define INT_LEAST32_MAX INT32_MAX

#define INT_LEAST64_MAX INT64_MAX

#define UINT_LEAST8_MAX UINT8_MAX

#define UINT_LEAST16_MAX UINT16_MAX

#define UINT_LEAST32_MAX UINT32_MAX

#define UINT_LEAST64_MAX UINT64_MAX

/* 7.18.2.3 Limits of fastest minimum-width integer types */ #define INT_FAST8_MIN INT8_MIN

#define INT_FAST16_MIN INT16_MIN

#define INT_FAST32_MIN INT32_MIN

#define INT_FAST64_MIN INT64_MIN

#define INT_FAST8_MAX INT8_MAX

#define INT_FAST16_MAX INT16_MAX

#define INT_FAST32_MAX INT32_MAX

#define INT_FAST64_MAX INT64_MAX

#define UINT_FAST8_MAX UINT8_MAX

#define UINT_FAST16_MAX UINT16_MAX

#define UINT_FAST32_MAX UINT32_MAX

#define UINT_FAST64_MAX UINT64_MAX

/* 7.18.2.4 Limits of integer types capable of holding object pointers */

#define INTPTR_MIN INT32_MIN

#define INTPTR_MAX INT32_MAX

#define UINTPTR_MAX UINT32_MAX

/* 7.18.2.5 Limits of greatest-width integer types */

#define INTMAX_MIN INT64_MIN

#define INTMAX_MAX INT64_MAX

#define UINTMAX_MAX UINT64_MAX

/* 7.18.3 Limits of other integer types */

#define PTRDIFF_MIN INT32_MIN

#define PTRDIFF_MAX INT32_MAX

#define SIG_ATOMIC_MIN INT32_MIN

#define SIG_ATOMIC_MAX INT32_MAX

#define SIZE_MAX UINT32_MAX

#ifndef WCHAR_MIN /* also in wchar.h */

#define WCHAR_MIN 0

#define WCHAR_MAX 0xffff /* UINT16_MAX */

#endif

/*

* wint_t is unsigned short for compatibility with MS runtime

*/

#define WINT_MIN 0

#define WINT_MAX 0xffff /* UINT16_MAX */

#endif /* !defined ( __cplusplus) || defined __STDC_LIMIT_MACROS */

/* 7.18.4 Macros for integer constants */

#if !defined ( __cplusplus) || defined (__STDC_CONSTANT_MACROS)

/* 7.18.4.1 Macros for minimum-width integer constants

Accoding to Douglas Gwyn :

"This spec was changed in ISO/IEC 9899:1999 TC1; in ISO/IEC 9899:1999 as initially published, the expansion was required

to be an integer constant of precisely matching type, which

is impossible to accomplish for the shorter types on most platforms, because C99 provides no standard way to designate

an integer constant with width less than that of type int.

TC1 changed this to require just an integer constant

*expression* with *promoted* type. "

*/

#define INT8_C(val) ((int8_t) + (val))

#define UINT8_C(val) ((uint8_t) + (val##U))

#define INT16_C(val) ((int16_t) + (val))

#define UINT16_C(val) ((uint16_t) + (val##U))

#define INT32_C(val) val##L

#define UINT32_C(val) val##UL

#define INT64_C(val) val##LL

#define UINT64_C(val) val##ULL

/* 7.18.4.2 Macros for greatest-width integer constants */

#define INTMAX_C(val) INT64_C(val)

#define UINTMAX_C(val) UINT64_C(val)

#endif /* !defined ( __cplusplus) || defined __STDC_CONSTANT_MACROS */

#endif

3、sha1.cpp

/* sha1.c */

/* 以下所用各种参量名称皆为sha-1在出版物上所用之公用名称*/

#include "sha1.h"

/*

* 以下是为SHA1 向左环形移位宏之定义

*/

#define SHA1CircularShift(bits,word) (((word) << (bits)) | ((word) >> (32-(bits))))

/* 局部函数原型*/

void SHA1PadMessage(SHA1Context *); /* 定义填充信息指针*/

void SHA1ProcessMessageBlock(SHA1Context *);

/*

* SHA1Reset

*

* 以下为数据初始化之操作

* Parameters:(参数设置)

* context: [in/out]

* The context to reset.

*

int SHA1Reset(SHA1Context *context)

{

if (!context)

{

return shaNull;

}

context->Length_Low = 0;

context->Length_High = 0;

context->Message_Block_Index = 0;

context->Intermediate_Hash[0] = 0x67452301;

context->Intermediate_Hash[1] = 0xEFCDAB89;

context->Intermediate_Hash[2] = 0x98BADCFE;

context->Intermediate_Hash[3] = 0x10325476;

context->Intermediate_Hash[4] = 0xC3D2E1F0;

context->Computed = 0;

context->Corrupted = 0;

return shaSuccess;

}

/*

* SHA1Result

*

* 以下为sha-1结果描述:

*:

* 该算法将会返回一个160比特的消息摘要队列

*

* 或者输出计算错误

*

*/

int SHA1Result( SHA1Context *context,

uint8_t Message_Digest[SHA1HashSize]) {

int i;

if (!context || !Message_Digest)

{

return shaNull;

}

if (context->Corrupted)

return context->Corrupted;

}

if (!context->Computed)

{

SHA1PadMessage(context);

for(i=0; i<64; ++i)

{

/* 消息清零*/

context->Message_Block[i] = 0;

}

context->Length_Low = 0; /* 长度清零*/

context->Length_High = 0;

context->Computed = 1;

}

for(i = 0; i < SHA1HashSize; ++i)

{

Message_Digest[i] = context->Intermediate_Hash[i>>2]

>> 8 * ( 3 - ( i & 0x03 ) );

}

return shaSuccess;

}

/*

* 以下为sha-1输入描述:

*

* 接收单位长度为8字节倍数的消息

*

*/

int SHA1Input( SHA1Context *context,

const uint8_t *message_array,

unsigned length)

{

if (!length)

{

return shaSuccess;

}

if (!context || !message_array)

{

return shaNull;

if (context->Computed)

{

context->Corrupted = shaStateError;

return shaStateError;

}

if (context->Corrupted)

{

return context->Corrupted;

}

while(length-- && !context->Corrupted)

{

context->Message_Block[context->Message_Block_Index++] =

(*message_array & 0xFF);

context->Length_Low += 8;

if (context->Length_Low == 0)

{

context->Length_High++;

if (context->Length_High == 0)

{

/* Message is too long */

context->Corrupted = 1;

}

}

if (context->Message_Block_Index == 64)

{

SHA1ProcessMessageBlock(context);

}

message_array++;

}

return shaSuccess;

}

/*

* 以下为sha-1消息块描述:

*

* 消息块长度为固定之512比特

*

void SHA1ProcessMessageBlock(SHA1Context *context)

{

const uint32_t K[] = { /* Constants defined in SHA-1 */

0x5A827999,

0x6ED9EBA1,

0x8F1BBCDC,

0xCA62C1D6

};

int t; /* 循环计数*/

uint32_t temp; /* 临时缓存*/

uint32_t W[80]; /* 字顺序*/

uint32_t A, B, C, D, E; /* 设置系统磁盘缓存块*/

/*

* 以下为初始化在W队列中的头16字数据

*/

for(t = 0; t < 16; t++)

{

W[t] = context->Message_Block[t * 4] << 24;

W[t] |= context->Message_Block[t * 4 + 1] << 16;

W[t] |= context->Message_Block[t * 4 + 2] << 8;

W[t] |= context->Message_Block[t * 4 + 3];

}

for(t = 16; t < 80; t++)

{

W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);

}

A = context->Intermediate_Hash[0];

B = context->Intermediate_Hash[1];

C = context->Intermediate_Hash[2];

D = context->Intermediate_Hash[3];

E = context->Intermediate_Hash[4];

/*

* 以下为定义算法所用之数学函数及其迭代算法描述

*/

for(t = 0; t < 20; t++)

{

temp = SHA1CircularShift(5,A) +

((B & C) | ((~B) & D)) + E + W[t] + K[0];

E = D;

D = C;

C = SHA1CircularShift(30,B);

B = A;

A = temp;

}

for(t = 20; t < 40; t++)

{

temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];

E = D;

D = C;

C = SHA1CircularShift(30,B);

B = A;

A = temp;

}

for(t = 40; t < 60; t++)

{

temp = SHA1CircularShift(5,A) +

((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];

E = D;

D = C;

C = SHA1CircularShift(30,B);

B = A;

A = temp;

}

for(t = 60; t < 80; t++)

{

temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];

E = D;

D = C;

C = SHA1CircularShift(30,B);

B = A;

A = temp;

}

/*

* 以下为迭代算法第80步(最后一步)描述

*/

context->Intermediate_Hash[0] += A;

context->Intermediate_Hash[1] += B;

context->Intermediate_Hash[2] += C;

context->Intermediate_Hash[3] += D;

context->Intermediate_Hash[4] += E;

context->Message_Block_Index = 0;

}

/*

* SHA1PadMessage

* 数据填充模块

*/

void SHA1PadMessage(SHA1Context *context)

{

if (context->Message_Block_Index > 55)

{

context->Message_Block[context->Message_Block_Index++] = 0x80;

while(context->Message_Block_Index < 64)

{

context->Message_Block[context->Message_Block_Index++] = 0;

}

SHA1ProcessMessageBlock(context);

while(context->Message_Block_Index < 56)

{

context->Message_Block[context->Message_Block_Index++] = 0;

}

}

else

{

context->Message_Block[context->Message_Block_Index++] = 0x80;

while(context->Message_Block_Index < 56)

{

context->Message_Block[context->Message_Block_Index++] = 0;

}

}

/*

* 把最后64位保存为数据长度

*/

context->Message_Block[56] = context->Length_High >> 24;

context->Message_Block[57] = context->Length_High >> 16;

context->Message_Block[58] = context->Length_High >> 8;

context->Message_Block[59] = context->Length_High;

context->Message_Block[60] = context->Length_Low >> 24;

context->Message_Block[61] = context->Length_Low >> 16;

context->Message_Block[62] = context->Length_Low >> 8;

context->Message_Block[63] = context->Length_Low;

SHA1ProcessMessageBlock(context);

}

4、sha1test.cpp

#include "stdint.h"

#include

#include

#include "sha1.h"

int main()

{

SHA1Context sha;

int i, j, err;

char ch[100] ;

uint8_t Message_Digest[20];

while(1){

printf("Input the string:");

gets(ch);

printf("The length of the string is:%d\n",strlen(ch));//sizeof()求的是所占内存大小,strlen()求的是字符串所占实际空间大小,以'\0'结束

printf( "Before SHA-1:%s\n", ch);

err = SHA1Reset(&sha);

if (err)

{

fprintf(stderr, "SHA1Reset Error %d.\n", err);

break;

}

err = SHA1Input(&sha, (const unsigned char *) ch, strlen(ch));

if (err)

{

fprintf(stderr, "SHA1Input Error %d.\n", err );

break; /* out of for i loop */

}

err = SHA1Result(&sha, Message_Digest);

if (err)

{

fprintf(stderr, "SHA1Result Error %d, could not compute message digest.\n", err);

}

else

{

printf("After SHA-1:");

for(i = 0; i < 20 ; ++i)

{

printf("%02X ", Message_Digest[i]);

}

printf("\n");

}

}

return 0;

}

JAVA线程池原理333

在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.将需处理的任务的数量大 使用线程池的好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销 2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存以及”过度切换”。 线程池工作原理:

线程池为线程生命周期开销问题和资源不足问题提供了解决方案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。其好处是,因为在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。 线程池的替代方案 线程池远不是服务器应用程序内使用多线程的唯一方法。如同上面所提到的,有时,为每个新任务生成一个新线程是十分明智的。然而,如果任务创建过于频繁而任务的平均处理时间过短,那么为每个任务生成一个新线程将会导致性能问题。 另一个常见的线程模型是为某一类型的任务分配一个后台线程与任务队列。AWT 和 Swing 就使用这个模型,在这个模型中有一个 GUI 事件线程,导致用户界面发生变化的所有工作都必须在该线程中执行。然而,由于只有一个 AWT 线程,因此要在 AWT 线程中执行任务可能要花费相当长时间才能完成,这是不可取的。因此,Swing 应用程序经常需要额外的工作线程,用于运行时间很长的、同 UI 有关的任务。 每个任务对应一个线程方法和单个后台线程(single-background-thread)方法在某些情形下都工作得非常理想。每个任务一个线程方法在只有少量运行时间很长的任务时工作得十分好。而只要调度可预见性不是很重要,则单个后台线程方法就工作得十分好,如低优先级后台任务就是这种情况。然而,大多数服务器应用程序都是面向处理大量的短期任务或子任务,因此往往希望具有一种能够以低开销有效地处理这些任务的机制以及一些资源管理和定时可预见性的措施。线程池提供了这些优点。 工作队列 就线程池的实际实现方式而言,术语“线程池”有些使人误解,因为线程池“明显的”实现在大多数情形下并不一定产生我们希望的结果。术语“线程池”先于Java 平台出现,因此它可能是较少面向对象方法的产物。然而,该术语仍继续广泛应用着。 虽然我们可以轻易地实现一个线程池类,其中客户机类等待一个可用线程、将任务传递给该线程以便执行、然后在任务完成时将线程归还给池,但这种方法却存在几个潜在的负面影响。例如在池为空时,会发生什么呢?试图向池线程传递任务的调用者都会发现池为空,在调用者等待一个可用的池线程时,它的线程将阻塞。我们之所以要使用后台线程的原因之一常常是为了防止正在提交的线程被阻塞。完全堵住调用者,如在线程池的“明显的”实现的情况,可以杜绝我们试图解决的问题的发生。 我们通常想要的是同一组固定的工作线程相结合的工作队列,它使用 wait() 和

线程池的原理与实现详解

线程池的原理与实现详解 https://www.wendangku.net/doc/6111864500.html,/article/41375.htm2013下面利用C 语言来实现一个简单的线程池,为了使得这个线程池库使用起来更加方便,特在C实现中加入了一些OO的思想,与Objective-C不同,它仅仅是使用了struct来模拟了c++中的类,其实这种方式在linux内核中大量可见 一. 线程池的简介 通常我们使用多线程的方式是,需要时创建一个新的线程,在这个线程里执行特定的任务,然后在任务完成后退出。这在一般的应用里已经能够满足我们应用的需求,毕竟我们并不是什么时候都需要创建大量的线程,并在它们执行一个简单的任务后销毁。 但是在一些web、email、database等应用里,比如彩铃,我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。这时,我们的应用有可能处于不停的创建线程并销毁线程的状态。虽说比起进程的创建,线程的创建时间已经大大缩短,但是如果需要频繁的创建线程,并且每个线程所占用的处理时间又非常简短,则线程创建和销毁带给处理器的额外负担也是很可观的。 线程池的作用正是在这种情况下有效的降低频繁创建销毁

线程所带来的额外开销。一般来说,线程池都是采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。 基于上面的技术,线程池将频繁创建和销毁线程所带来的开销分摊到了每个具体执行的任务上,执行的次数越多,则分摊到每个任务上的开销就越小。 当然,如果线程创建销毁所带来的开销与线程执行任务的开销相比微不足道,可以忽略不计,则线程池并没有使用的必要。比如,FTP、Telnet等应用时。 二. 线程池的设计 下面利用C语言来实现一个简单的线程池,为了使得这个线程池库使用起来更加方便,特在C实现中加入了一些OO的思想,与Objective-C不同,它仅仅是使用了struct来模拟

操作系统精髓与设计原理课后答案

操作系统精髓与设计原理课后答案 第1章计算机系统概述 1.1列出并简要地定义计算机的四个主要组成部分。 主存储器,存储数据和程序;算术逻辑单元,能处理二进制数据;控制单元,解读存储器中的指令并且使他们得到执行;输入/输出设备,由控制单元管理。 1.2定义处理器寄存器的两种主要类别。 用户可见寄存器:优先使用这些寄存器,可以使机器语言或者汇编语言的程序员减少对主存储器的访问次数。对高级语言而言,由优化编译器负责决定把哪些变量应该分配给主存储器。一些高级语言,如C语言,允许程序言建议编译器把哪些变量保存在寄存器中。 控制和状态寄存器:用以控制处理器的操作,且主要被具有特权的操作系统例程使用,以控制程序的执行。 1.3一般而言,一条机器指令能指定的四种不同操作是什么? 处理器-寄存器:数据可以从处理器传送到存储器,或者从存储器传送到处理器。 处理器-I/O:通过处理器和I/O模块间的数据传送,数据可以输出到外部设备,或者从外部设备输入数据。 数据处理:处理器可以执行很多关于数据的算术操作或逻辑操作。 控制:某些指令可以改变执行顺序。 1.4什么是中断? 中断:其他模块(I/O,存储器)中断处理器正常处理过程的机制。 1.5多中断的处理方式是什么? 处理多中断有两种方法。第一种方法是当正在处理一个中断时,禁止再发生中断。第二种方法是定义中断优先级,允许高优先级的中断打断低优先级的中断处理器的运行。 1.6内存层次的各个元素间的特征是什么? 存储器的三个重要特性是:价格,容量和访问时间。 1.7什么是高速缓冲存储器? 高速缓冲存储器是比主存小而快的存储器,用以协调主存跟处理器,作为最近储存地址的缓冲区。1.8列出并简要地定义I/O操作的三种技术。 可编程I/O:当处理器正在执行程序并遇到与I/O相关的指令时,它给相应的I/O模块发布命令(用以执行这个指令);在进一步的动作之前,处理器处于繁忙的等待中,直到该操作已经完成。 中断驱动I/O:当处理器正在执行程序并遇到与I/O相关的指令时,它给相应的I/O模块发布命令,并继续执行后续指令,直到后者完成,它将被I/O模块中断。如果它对于进程等待I/O的完成来说是不必要的,可能是由于后续指令处于相同的进程中。否则,此进程在中断之前将被挂起,其他工作将被执行。 直接存储访问:DMA模块控制主存与I/O模块间的数据交换。处理器向DMA模块发送一个传送数据块的请求,(处理器)只有当整个数据块传送完毕后才会被中断。 1.9空间局部性和临时局部性间的区别是什么? 空间局部性是指最近被访问的元素的周围的元素在不久的将来可能会被访问。临时局部性(即时间局部性)是指最近被访问的元素在不久的将来可能会被再次访问。 1.10开发空间局部性和时间局部性的策略是什么? 空间局部性的开发是利用更大的缓冲块并且在存储器控制逻辑中加入预处理机制。时间局部性的开发是利用在高速缓冲存储器中保留最近使用的指令及数据,并且定义缓冲存储的优先级。 第2章操作系统概述

java深入理解线程池

深入研究线程池 一.什么是线程池? 线程池就是以一个或多个线程[循环执行]多个应用逻辑的线程集合. 注意这里用了线程集合的概念是我生造的,目的是为了区分执行一批应用逻辑的多个线程和 线程组的区别.关于线程组的概念请参阅基础部分. 一般而言,线程池有以下几个部分: 1.完成主要任务的一个或多个线程. 2.用于调度管理的管理线程. 3.要求执行的任务队列. 那么如果一个线程循环执行一段代码是否是线程池? 如果极端而言,应该算,但实际上循环代码应该算上一个逻辑单元.我们说最最弱化的线程池 应该是循环执行多个逻辑单元.也就是有一批要执行的任务,这些任务被独立为多个不同的执行单元.比如: int x = 0; while(true){ x ++; } 这就不能说循环中执行多个逻辑单元,因为它只是简单地对循环外部的初始变量执行++操作. 而如果已经有一个队列 ArrayList al = new ArrayList(); for(int i=0;i<10000;i++){ al.add(new AClass()); } 然后在一个线程中执行: while(al.size() != 0){ AClass a = (AClass)al.remove(0); a.businessMethod(); } 我们说这个线程就是循环执行多个逻辑单元.可以说这个线程是弱化的线程池.我们习惯上把这些相对独立的逻辑单元称为任务. 二.为什么要创建线程池? 线程池属于对象池.所有对象池都具有一个非常重要的共性,就是为了最大程度复用对象.那么 线程池的最重要的特征也就是最大程度利用线程. 从编程模型模型上说讲,在处理多任务时,每个任务一个线程是非常好的模型.如果确实可以这么做我们将可以使用编程模型更清楚,更优化.但是在实际应用中,每个任务一个线程会使用系统限入"过度切换"和"过度开销"的泥潭. 打个比方,如果可能,生活中每个人一辆房车,上面有休息,娱乐,餐饮等生活措施.而且道路交道永远不堵车,那是多么美好的梦中王国啊.可是残酷的现实告诉我们,那是不可能的.不仅每个人一辆车需要无数多的社会资源,而且地球上所能容纳的车辆总数是有限制的. 首先,创建线程本身需要额外(相对于执行任务而必须的资源)的开销.

普元EOS工作流引擎设计原理

EOS工作流引擎工作原理 作者:Gocom注册用户dogreet(李国生) 1. 工作流基础知识 ……略 2. EOS工作流引擎工作原理 本文是我在工作之余写的一点我对EOS工作流的了解,我的理解不一定全是对的,可能会与引擎的真正的面目有出入。所以只能提供给大家一点参考。 2.1. EOS工作流引擎核心调度算法 EOS工作流最重要的组成部分是它的核心调度算法,在我们没有深入研究它的工作原理之前我们认为它的工作原理是在工作项,活动和流程实例对象上加了一些标志位来驱动流程的运转。认为其引擎完全是个由数据库来驱动流程的引擎(安徽二期的工作流平台好象就是以库表来驱动流程的运转),其实它是由事件来驱动流程运转的引擎,数据库只是把引擎运转前后的状态持久化。在我近来在工作之余对其引擎的工作原理进行跟踪才弄明白在EOS帮助文档上介绍的“事件驱动”的工作流引擎。 2.1.1. EOS工作流引擎的事件类型

以上的每个事件都是原子的不可分割的。其中一系列事件的集合通过EOS引擎事件调度机制实现我们平时在工作中经常遇到的如启动流程,结束工作项等等。(在事件类型类中EOS定义了29种事件,但在事件工厂类中EOS定义了26种类型。) 1.1.1. EOS工作流事件调度机制 EOS事件的调度服务是在工作流引擎初始化时通过服务工厂类加载到内存中(ServiceFactory.initEventService())。用户可以通过服务工厂类(ServiceFactory)取得JVM的唯一事件服务实例进行事务调度。所有的事件程序入口都是事件类(EventService),这个类其实是个接口,其有两个实现类,一个是单线程的实现类SingleThreadEventService (在实现代码中其实不是单线程,而是单例的对象),一个是多线程的实现类MulThreadThreadSvc,(其实现方式不在这里详细说明,多线程的类后面又跟了一大堆的线程池实现代码),在事件服务类中有一个属性类是WFEventDisposer,这个类包含了事

Tomcat线程池实现简介

Tomcat线程池实现简介 目前市场上常用的开源Java Web容器有Tomcat、Resin和Jetty。其中Resin从V3.0后需要购买才能用于商业目的,而其他两种则是纯开源的。可以分别从他们的网站上下载最新的二进制包和源代码。 作为Web容器,需要承受较高的访问量,能够同时响应不同用户的请求,能够在恶劣环境下保持较高的稳定性和健壮性。在HTTP服务器领域,Apache HTTPD的效率是最高的,也是最为稳定的,但它只能处理静态页面的请求,如果需要支持动态页面请求,则必须安装相应的插件,比如mod_perl可以处理Perl脚本,mod_python可以处理Python脚本。 上面介绍的三中Web容器,都是使用Java编写的HTTP服务器,当然他们都可以嵌到Apache 中使用,也可以独立使用。分析它们处理客户请求的方法有助于了解Java多线程和线程池的实现方法,为设计强大的多线程服务器打好基础。 Tomcat是使用最广的Java Web容器,功能强大,可扩展性强。最新版本的Tomcat(5.5.17)为了提高响应速度和效率,使用了Apache Portable Runtime(APR)作为最底层,使用了APR 中包含Socket、缓冲池等多种技术,性能也提高了。APR也是Apache HTTPD的最底层。可想而知,同属于ASF(Apache Software Foundation)中的成员,互补互用的情况还是很多的,虽然使用了不同的开发语言。 Tomcat 的线程池位于tomcat-util.jar文件中,包含了两种线程池方案。方案一:使用APR 的Pool技术,使用了JNI;方案二:使用Java实现的ThreadPool。这里介绍的是第二种。如果想了解APR的Pool技术,可以查看APR的源代码。 ThreadPool默认创建了5个线程,保存在一个200维的线程数组中,创建时就启动了这些线程,当然在没有请求时,它们都处理“等待”状态(其实就是一个while循环,不停的等待notify)。如果有请求时,空闲线程会被唤醒执行用户的请求。 具体的请求过程是:服务启动时,创建一个一维线程数组(maxThread=200个),并创建空闲线程(minSpareThreads=5个)随时等待用户请求。当有用户请求时,调用threadpool.runIt(ThreadPoolRunnable)方法,将一个需要执行的实例传给ThreadPool中。其中用户需要执行的实例必须实现ThreadPoolRunnable接口。ThreadPool 首先查找空闲的线程,如果有则用它运行要执行ThreadPoolRunnable;如果没有空闲线程并且没有超过maxThreads,就一次性创建minSpareThreads个空闲线程;如果已经超过了maxThreads了,就等待空闲线程了。总之,要找到空闲的线程,以便用它执行实例。找到后,将该线程从线程数组中移走。接着唤醒已经找到的空闲线程,用它运行执行实例(ThreadPoolRunnable)。运行完ThreadPoolRunnable后,就将该线程重新放到线程数组中,作为空闲线程供后续使用。 由此可以看出,Tomcat的线程池实现是比较简单的,ThreadPool.java也只有840行代码。用一个一维数组保存空闲的线程,每次以一个较小步伐(5个)创建空闲线程并放到线程池中。使用时从数组中移走空闲的线程,用完后,再“归还”给线程池。ThreadPool提供的仅仅是线程池的实现,而如何使用线程池也是有很大学问的。让我们看看Tomcat是如何使用ThreadPool的吧。 Tomcat有两种EndPoint,分别是AprEndpoint和PoolTcpEndpoint。前者自己实现了一套线

线程池原理 C++实现

线程池原理及创建(C++实现) 时间:2010‐02‐25 14:40:43来源:网络 作者:未知 点击:2963次 本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量。文章的最后,我们给出一个 本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量。文章的最后,我们给出一个简单示例程序,通过该示例程序,我们会发现,通过该线程池框架执行多线程任务是多么的简单。 为什么需要线程池 目前的大多数网络服务器,包括Web服务器、Email服务器以及数据库服务器等都具有一个共同点,就是单位时间内必须处理数目巨大的连接请求,但处理时间却相对较短。 传统多线程方案中我们采用的服务器模型则是一旦接受到请求之后,即创建一个新的线程,由该线程执行任务。任务执行完毕后,线程退出,这就是是“即时创建,即时销毁”的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数极其频繁,那么服务器将处于不停的创建线程,销毁线程的状态。 我们将传统方案中的线程执行过程分为三个过程:T1、T2、T3。 T1:线程创建时间 T2:线程执行时间,包括线程的同步等时间 T3:线程销毁时间

那么我们可以看出,线程本身的开销所占的比例为(T1+T3) / (T1+T2+T3)。如果线程执行的时间很短的话,这比开销可能占到20%‐50%左右。如果任务执行时间很频繁的话,这笔开销将是不可忽略的。 除此之外,线程池能够减少创建的线程个数。通常线程池所允许的并发线程是有上界的,如果同时需要并发的线程数超过上界,那么一部分线程将会等待。而传统方案中,如果同时请求数目为2000,那么最坏情况下,系统可能需要产生2000个线程。尽管这不是一个很大的数目,但是也有部分机器可能达不到这种要求。 因此线程池的出现正是着眼于减少线程池本身带来的开销。线程池采用预创建的技术,在应用程序启动之后,将立即创建一定数量的线程(N1),放入空闲队列中。这些线程都是处于阻塞(Suspended)状态,不消耗CPU,但占用较小的内存空间。当任务到来后,缓冲池选择一个空闲线程,把任务传入此线程中运行。当N1个线程都在处理任务后,缓冲池自动创建一定数量的新线程,用于处理更多的任务。在任务执行完毕后线程也不退出,而是继续保持在池中等待下一次的任务。当系统比较空闲时,大部分线程都一直处于暂停状态,线程池自动销毁一部分线程,回收系统资源。 基于这种预创建技术,线程池将线程创建和销毁本身所带来的开销分摊到了各个具体的任务上,执行次数越多,每个任务所分担到的线程本身开销则越小,不过我们另外可能需要考虑进去线程之间同步所带来的开销。 构建线程池框架 一般线程池都必须具备下面几个组成部分: 线程池管理器:用于创建并管理线程池 工作线程: 线程池中实际执行的线程

IOCP 原理 代码

Windows I/O完成端口 2009-10-30 10:51 WINDOWS完成端口编程 1、基本概念 2、WINDOWS完成端口的特点 3、完成端口(Completion Ports )相关数据结构和创建 4、完成端口线程的工作原理 5、Windows完成端口的实例代码 WINDOWS完成端口编程 摘要:开发网络程序从来都不是一件容易的事情,尽管只需要遵守很少的一些规则:创建socket,发起连接,接受连接,发送和接收数据,等等。真正的困难在于:让你的程序可以适应从单单一个连接到几千个连接乃至于上万个连接。利用Windows完成端口进行重叠I/O的技术,可以很方便地在Windows平台上开发出支持大量连接的网络服务程序。本文介绍在Windows平台上使用完成端口模型开发的基本原理,同时给出实际的例子。本文主要关注C/S结构的服务器端程序,因为一般来说,开发一个大容量、具有可扩展性的winsock程序就是指服务程序。 1、基本概念 设备---指windows操作系统上允许通信的任何东西,比如文件、目录、串行口、并行口、邮件槽、命名管道、无名管道、套接字、控制台、逻辑磁盘、物理磁盘等。绝大多数与设备打交道的函数都是CreateFile/ReadFile/WriteFile 等,所以我们不能看到**File函数就只想到文件设备。 与设备通信有两种方式,同步方式和异步方式:同步方式下,当调用ReadFile这类函数时,函数会等待系统执行完所要求的工作,然后才返回;异步方式下,ReadFile这类函数会直接返回,系统自己去完成对设备的操作,然后以某种方式通知完成操作。 重叠I/O----顾名思义,就是当你调用了某个函数(比如ReadFile)就立刻返回接着做自己的其他动作的时候,系统同时也在对I/0设备进行你所请求的操作,在这段时间内你的程序和系统的内部动作是重叠的,因此有更好的性能。所以,重叠I/O是在异步方式下使用I/O设备的。重叠I/O需要使用的一个非常重要的数据结构:OVERLAPPED。 2、WINDOWS完成端口的特点 Win32重叠I/O(Overlapped I/O)机制允许发起一个操作,并在操作完成之后接收信息。对于那种需要很长时间才能完成的操作来说,重叠IO机制尤其有用,因为发起重叠操作的线程在重叠请求发出后就可以自由地做别的事情了。在WinNT和Win2000上,提供的真正可扩展的I/O模型就是使用完成端口(Completion Port)的重叠I/O。完成端口---是一种WINDOWS内核对象。完成端口用于异步方式的重叠I/0情况下,当然重叠I/O不一定非得使用完成端口不可,同样设备内核对象、事件对象、告警I/0等也可使用。但是完成端口内部提

跟我学VS#语言编程技术——C#中的线程池Thread Pool技术及应用示例

1.1跟我学VS#语言编程技术——C#中的线程池Thread Pool技术及应用示例1.1.1C#中的线程池Thread Pool技术及应用示例 1、线程池Thread Pool技术概述 我们知道,大部分应用程序都是通过线程工作的,该线程等待一些引入的连接,一旦接收到一个连接,就会创建一个新的线程,并且要求这个线程服务于这个新的连接。 在此种工作方式下,当线程比较多的时候,系统的开销将会相当大。减少系统开销的一个方法就是使用一个线程池来处理,特别是关于在服务应用程序中使用线程的问题。 在服务器端的应用程序中几乎都采用了“线程池”技术,这主要是为了提高系统效率。因为如果服务器对应每一个请求就创建一个线程的话,在很短的一段时间内就会产生很多创建和销毁线程动作,导致服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。线程池就是为了尽量减少这种情况的发生。 2、线程池的工作原理 所谓线程池,就是在内存中等待工作的线程,系统会根据工作的情况,自动地创建并管理新的线程。其工作原理如下图所示:

3、ThreadPool类 在.NET中,通过System.Threading.ThreadPool类,每个进程都自动带有一个线程池,而且每个进程至多只能有一个线程池,可以在多个不同的行为间共享线程池。 上面我们已经知道了线程池主要用于服务引入的连接,但同时也还可以周期性地进行其它方面的服务,比如检查服务器上的磁盘空间,确保服务器高速运行,检查电子邮件以及服务客户连接等等。 其实,线程池可以使线程变得更容易,很明显还需要处理同步问题,但我们不需要真实地创建线程,.NET会帮助我们做这些。

100行Java代码构建一个线程池

100行Java代码构建一个线程池 本示例程序由三个类构成,第一个是TestThreadPool类,它是一个测试程序,用来模拟客户端的请求,当你运行它时,系统首先会显示线程池的初始化信息,然后提示你从键盘上输入字符串,并按下回车键,这时你会发现屏幕上显示信息,告诉你某个线程正在处理你的请求,如果你快速地输入一行行字符串,那么你会发现线程池中不断有线程被唤醒,来处理你的请求,在本例中,我创建了一个拥有10个线程的线程池,如果线程池中没有可用线程了,系统会提示你相应的警告信息,但如果你稍等片刻,那你会发现屏幕上会陆陆续续提示有线程进入了睡眠状态,这时你又可以发送新的请求了。 第二个类是ThreadPoolManager类,顾名思义,它是一个用于管理线程池的类,它的主要职责是初始化线程池,并为客户端的请求分配不同的线程来进行处理,如果线程池满了,它会对你发出警告信息。 最后一个类是SimpleThread类,它是Thread类的一个子类,它才真正对客户端的请求进行处理,SimpleThread在示例程序初始化时都处于睡眠状态,但如果它接受到了ThreadPoolManager类发过来的调度信息,则会将自己唤醒,并对请求进行处理。 首先我们来看一下TestThreadPool类的源码: //TestThreadPool.java 1 import java.io.*; 2 3 4 public class TestThreadPool 5 { 6 public static void main(String[] args) 7 { 8 try{ 9 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 10 String s; 11 ThreadPoolManager manager = new ThreadPoolManager(10); 12 while((s = br.readLine()) != null) 13 {

JAVA中的同步与异步问题 线程和线程池的重要知识

java线程同步与异步线程池 java线程同步与异步线程池 1)多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理。显然这是由于全局资源造成的,有时为了解 决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲 系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求 不到,怎么办,A线程只能等待下去 异步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程 仍然请求的到,A线程无需等待

显然,同步最最安全,最保险的。而异步不安全,容易导致死锁,这样一个线程死掉就会导致整个 进程崩溃,但没有同步机制的存在,性能会有所提升 java中实现多线程 1)继承Thread,重写里面的run方法 2)实现runnable接口 Doug Lea比较推荐后者,第一,java没有单继承的限制第二,还可以隔离代码 线程池 要知道在计算机中任何资源的创建,包括线程,都需要消耗系统资源的。在WEB服务中,对于web服 务器的响应速度必须要尽可能的快,这就容不得每次在用户提交请求按钮后,再创建线程提供服务 。为了减少用户的等待时间,线程必须预先创建,放在线程池中,线程池可以用HashTable这种数

据结构来实现,看了Apach HTTP服务器的线程池的源代码,用是就是HashTable,KEY 用线程对象, value用ControlRunnable,ControlRunnable是线程池中唯一能干活的线程,是它指派线程池中的 线程对外提供服务。 出于安全考虑,Apach HTTP服务器的线程池它是同步的。听说weblogic有异步的实现方式,没有研 究过,不敢确定 --------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------一、关键字: thread(线程)、thread-safe(线程安全)、intercurrent(并发的) synchronized(同步的)、asynchronized(异步的)、 volatile(易变的)、atomic(原子的)、share(共享) 二、总结背景: 一次读写共享文件编写,嚯,好家伙,竟然揪出这些零碎而又是一路的知识点。于是乎,

操作系统原理

第1章 (1)什么是操作系统,操作系统的基本功能是什么?(2)基本概念:中断向量(p7)…. (3)多道程序设计优点? 第2章 (1)什么是系统调用,作用?P41系统调用的分类型(2)机制和策略的区别?P49

第3章 (1)为什么要采用多进程? (2)进程的结构(资源):代码段、数据段、BSS段、堆、栈、PCB(又有什么P73) (3)进程有哪些状态,怎么切换?P73 图3.2 (4)作业队列,调度就绪队列。长期调度程序,短期调度程序,IO为主,CPU为主,,P77

(5)P78 进程的上下文切换流程,在哪些地方涉及它?(6)linux下,用fork创建进程时,资源是复制的?P81 (7)P85 为什么要需要进程间通信的机制,有哪两大类? 第4章 线程是执行的最小单元,进程是管理(资源分配)的最小单位。 (1)多线程的模型,每种模型优缺点是什么?P114 (2)线程的资源有哪些?P111,和同一个进程的其它线程共享哪些数据?

(3)多线程的优点是什么?p112 (4)pthread编程习题4.7 (5)在线程中调用fork函数可能有什么样问题P122 (6)取消线程有哪两种方式,区别? (7)什么叫线程池,进程池。有什么优点和缺点 (8)为什么说linux下并不真正区分进程和线程.P127 第5章 (1)为什么需要调度策略?

(2)CPU区间,IO区间的概念。 (3)如何区分抢占式内核和非抢占式内核,调度策略发生在哪些情况下?P135 (4)在发生调度时,哪些信息是必须保护的. 当前程序的位置,当前程序的状态,当前的临时数据 (5)调度的准则有哪些:P137 (6)调度算法: FCFS SJF:不能实现的原因是什么?有不有什么解决的方案?P140

大数据处理之Java线程池使用

大数据处理之Java线程池使用 前言:最近在做分布式海量数据处理项目,使用到了java的线程池,所以搜集了一些资料对它的使用做了一下总结和探究, 前面介绍的东西大多都是从网上搜集整理而来。文中最核心的东西在于后面两节无界队列线程池和有界队列线程池的实例使用以及线上问题处理方案。 1. 为什么要用线程池? 在Java中,如果每当一个请求到达就创建一个新线程,开销是相当大的。在实际使用中,每个请求创建新线程的服务器 在创建和销毁线程上花费的时间和消耗的系统资源,甚至可能要比花在实际处理实际的用户请求的时间和资源要多的多。除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源。如果在一个JVM中创建太多的线程,可能会导致系统由于过度消耗内存或者“切换过度”而导致系统资源不足。为了防止资源不足,服务器应用程序需要一些办法来限制任何给定时刻处理的请求数目,尽可能减少创建和销毁线程的次数,特别是一些资源耗费比较大的线程的创建和销毁,尽量利用已有对象来进行服务,这就是“池化资源”技术产生的原因。 线程池主要用来解决线程生命周期开销问题和资源不足问题,通过对多个任务重用线程,线程创建的开销被分摊到多个任务上了,而且由于在请求到达时线程已经存在,所以消除了创建所带来的延迟。这样,就可以立即请求服务,使应用程序响应更快。另外,通过适当的调整线程池中的线程数据可以防止出现资源不足的情况。 网上找来的这段话,清晰的描述了为什么要使用线程池,使用线程池有哪些好处。工程项目中使用线程池的场景比比皆是。 本文关注的重点是如何在实战中来使用好线程池这一技术,来满足海量数据大并发用户请求的场景。 2. ThreadPoolExecutor类 Java中的线程池技术主要用的是ThreadPoolExecutor 这个类。先来看这个类的构造函数, ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,

线程池的使用

什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。 下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。 pool_init()函数预先创建好max_thread_num个线程,每个线程执thread_routine ()函数。该函数中 1. while (pool->cur_queue_size == 0) 2. { 3. pthread_cond_wait (&(pool->queue_ready),&(pool->queue_lock)); 4. } 表示如果任务链表中没有任务,则该线程出于阻塞等待状态。否则从队列中取出任务并执行。 pool_add_worker()函数向线程池的任务链表中加入一个任务,加入后通过调用 pthread_cond_signal (&(pool->queue_ready))唤醒一个出于阻塞状态的线程(如果有的话)。 pool_destroy ()函数用于销毁线程池,线程池任务链表中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出。 下面贴出完整代码 1. #include 2. #include 3. #include 4. #include 5. #include 6. #include 7. 8. /* 9. *线程池里所有运行和等待的任务都是一个CThread_worker

EOS工作流引擎原理

EOS工作流引擎工作原理 工作流基础知识 EOS工作流引擎工作原理 本文是我在工作之余写的一点我对EOS工作流的了解,我的理解不一定全是对的,可能会与引擎的真正的面目有出入。所以只能提供给大家一点参考。 EOS工作流引擎核心调度算法 EOS工作流最重要的组成部分是它的核心调度算法,在我们没有深入研究它的工作原理之前我们认为它的工作原理是在工作项,活动和流程实例对象上加了一些标志位来驱动流程的运转。认为其引擎完全是个由数据库来驱动流程的引擎(安徽二期的工作流平台好象就是以库表来驱动流程的运转),其实它是由事件来驱动流程运转的引擎,数据库只是把引擎运转前后的状态持久化。在我近来在工作之余对其引擎的工作原理进行跟踪才弄明白在EOS 帮助文档上介绍的“事件驱动”的工作流引擎。

度机制实现我们平时在工作中经常遇到的如启动流程,结束工作项等等。(在事件类型类中EOS定义了29种事件,但在事件工厂类中EOS定义了26种类型。) 1.1. 2.EOS工作流事件调度机制 EOS事件的调度服务是在工作流引擎初始化时通过服务工厂类加载到内存中(ServiceFactory.initEventService())。用户可以通过服务工厂类(ServiceFactory)取得JVM 的唯一事件服务实例进行事务调度。所有的事件程序入口都是事件类(EventService),这个类其实是个接口,其有两个实现类,一个是单线程的实现类SingleThreadEventService(在实现代码中其实不是单线程,而是单例的对象),一个是多线程的实现类MulThreadThreadSvc,(其实现方式不在这里详细说明,多线程的类后面又跟了一大堆的线程池实现代码),在事件服务类中有一个属性类是WFEventDisposer,这个类包含了事件的注册,事件的发布,事件的注册是一个静态代码块实现的。注册了上节描述的29种事件,其实就是把相应的事件代码注册到相应的处理类,事件处理类共用5个(ProcessScheduler,ActivityExecuter,ExceptionHandler,WorkItemHandler,ApplicationHandler),对应事件代码的前5个数字;共有事件的发布有两种,一种是正常发布,一种是无异常的发布(即在具体执行事件时关闭了异常处理)。所谓的事件发布是给事件服务类传递一个事件对象(WFEvent类),这个事件对象包含了事件类型,线程名,事件ID,流程定义ID,活动定义ID,活动实例ID,和工作项ID等等。 以上简要的描述了事件模型,下面来拿我们平时用的最多的一个构件:结束工作项来详细跟踪它的事件处理。结束工作项可能是最具有代表性的一个流程动作,因为在做这个时间后遍历了整个流程实例的流程: 1,用户通过引擎的API调用WorkItemManager类的finishWorkItem方法,该方法通过服务工厂取得持久层的数据访问服务,并根据workitemID取得 WFWorkItem对象。做相关的判断后通过事件工厂类的 createFinishWorkItemEvent方法创建个事件代码为3004的事件对象(WFEvent)。 然后通过服务工厂类取得事件服务类把该事件对象发布给事件处理服务。从此 刻就开始了EOS事件调度服务的运转。 2,事件服务类(拿单线程事件服务类做例子)拿到这个事件类后把该事件通过WFEventDisposer发布该事件。具体的发布过程很简单,即判断该事件类型是 否已注册,如果已经注册则取到改事件代码的注册类。该代码是3004,则应取 WorkItemHandler。然后调用WorkItemHandler的invoke()方法,3,WorkItemHandler类invoke()中写到:if(event.getType() == 30004) {finishWorkItem(event);}则找到该方法,该方法开始做了相关的判断后做相关标 志位的修改:置当前工作项的状态为12,然后判断当前活动是否结束。(大概 的算法是取得已经结束的工作项和该活动总的工作项,取得活动定义的多工作 项是否启动。如果是多工作项则判断完成个数策略:是按百分比还是按操作员

线程池设计原理

了解JAVA多线程编程的人都知道,要产生一个线程有两种方法,一是类直接继承Thread 类并实现其run()方法;二是类实现Runnable接口并实现其run()方法,然后新建一个以该类为构造方法参数的Thread,类似于如下形式: Thread t=new Thread(myRunnable)。而最终使线程启动都是执行Thread类的start()方法。 在JAVA中,一个线程一旦运行完毕,即执行完其run()方法,就不可以重新启动了。此时这个线程对象也便成了无用对象,等待垃圾回收器的回收。下次想再启动这个线程时,必须重新new出一个线程对象再start之。频繁地创建和销毁对象不仅影响运行效率,还可能因无用线程对象来不及被回收而产生大量的垃圾内存,在存储空间和处理速度都相对受限的移动平台上这种影响尤为显著。那么,能否重新设计一种线程类,使其能够被反复启动而无需频繁地创建和销毁对象呢? 当然可以。下面我就介绍一下对这个“可重启线程”类的设计。 首先必须明确,如果仍是把想要线程去做的任务直接放在线程的run()方法中,是无论如何无法达成目的的,因为就像上面已经说的,JAVA的线程类一旦执行完run()方法就无法再启动了。所以唯一可行的办法是,把用户程序要做的run()方法(不妨称作“用户过程”)套在线程实际的run()方法内部的while循环体内,当用户过程执行完后使线程wait。当调用restart方法重启线程时,实际就是唤醒等待中的线程使之开始下一次while循环。大致的思想确定了,下面的代码就很好理解了: public class ReusableThread implements Runnable { //线程状态监听者接口 public interface ThreadStateListener { public abstract void onRunOver(ReusableThread thread);//当用户过程执行完毕后调用的方法 } public static final byte STATE_READY=0; //线程已准备好,等待开始用户过程 public static final byte STATE_STARTED=1; //用户过程已启动

IOCP完成端口原理-详解

本文主要探讨一下windows平台上的完成端口开发及其与之相关的几个重要的技术概念,这些概念都是与基于IOCP的开发密切相关的,对开发人员来讲,又不得不给予足够重视的几个概念: 1) 基于IOCP实现的服务吞吐量 2)IOCP模式下的线程切换 3)基于IOCP实现的消息的乱序问题。 一、IOCP简介 提到IOCP,大家都非常熟悉,其基本的编程模式,我就不在这里展开了。在这里我主要是把IOCP中所提及的概念做一个基本性的总结。IOCP的基本架构图如下: 如图所示:在IOCP中,主要有以下的参与者: --》完成端口:是一个FIFO队列,操作系统的IO子系统在IO操作完成后,会把相应的IO packet放入该队列。 --》等待者线程队列:通过调用GetQueuedCompletionStatus API,在完成端口上等待取下一个IO packet。 --》执行者线程组:已经从完成端口上获得IO packet,在占用CPU进行处理。除了以上三种类型的参与者。我们还应该注意两个关联关系,即: --》IO Handle与完成端口相关联:任何期望使用IOCP的方式来处理IO请求的,必须将相应的IO Handle与该完成端口相关联。需要指出的时,这里的IO Handle,可以是File的Handle,或者是Socket的Handle。 --》线程与完成端口相关联:任何调用GetQueuedCompletionStatus API的线程,都将与该完成端口相关联。在任何给定的时候,该线程只能与一个完成端口相关联,与最后一次调用的GetQueuedCompletionStatus为准。 二、高并发的服务器(基于socket)实现方法

相关文档
相关文档 最新文档