当前位置:文档之家› 多线程基础与提高

多线程基础与提高

多线程基础与提高
多线程基础与提高

C++多线程(一) (2)

C++多线程(二) (5)

C++多线程(三) (11)

C++多线程(四) (25)

C++多线程(五) (35)

C++多线程(六) (39)

C++多线程(七) (45)

C++多线程(八) (50)

C++多线程(九) (58)

C++多线程(十) (70)

C++多线程(一)

WIN 多线程API

一简单实例

比较简单的代码,创建10个线程,其中使第4个线程在一创建就挂起,等到其他的线程执行的差不多的时候再使第4个线程恢复执行。

#include

#include

#include

#define THREAD_NUM 10

DWORD WINAPI PrintThreads (LPVOID);

int main ()

{

HANDLE hThread[THREAD_NUM];

DWORD dwThreadID[THREAD_NUM];

for (int i=0; i

{

int isStartImmediate = 0;

if(3 == i)

isStartImmediate = CREATE_SUSPENDED;

hThread[i]=CreateThread(NULL, // security attributes that should be applied to the new thread,

// this is for NT. Use NULL to get the default security attributes. Use NULL for win95

0, // default size of 1MB can be passed by passing zero.

PrintThreads, // function name:address of the function where the new thread starts.

(LPVOID)i, // parameter(void pointer): pointer to the 32 bit parameter that will be passed into the thread

isStartImmediate, // flags to control the creation of the thread. Passing zero starts the thread immediately.

// Passing CREATE_SUSPENDED suspends the thread until the ResumeThread( ) function is called.

&dwThreadID[i] // pointer to a 32-bit variable that receives the thread identifier.

);

if (hThread[i])

{

printf ("Thread launched successfully\n");

}

}

printf("Start sleep 100, and let other thread excute\n");

Sleep (100);

printf("Start sleep 100, and thread 3 excute\n");

ResumeThread(hThread[3]);

Sleep(100);

for(int i = 0; i

{

if (hThread[i])

{

CloseHandle(hThread[i]); // You need to use this to release kernel objects when you are done using them.

// If a process exits without closing the thread handle,

// the operating system drops the reference counts for those objects.

// But if a process frequently creates threads without closing the handles,

// there could be hundreds of thread kernel objects lying around and these resource leaks can have a big hit on performance.

}

}

return (0);

}

//function PrintThreads

DWORD WINAPI PrintThreads (LPVOID num)

{

for (int i=0; i<10; i++)

printf ("Thread Number is %d%d%d\n", num,num,num);

return0;

}

二其他基本API的说明

CreateThread() 调用成功返回句柄和一个id。

CloseHandle() 关闭一个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄.

SuspendThread(HANDLE) 允许开发人员将HANDLE指定的线程挂起,如果要挂起的线程占有共享资源,则可能导致死锁。

ResumeThread(HANDLE) 恢复指定的线程。

TerminateThread() 立即终止线程的工作,不做任何清理工作。

ExitThread() 线程函数返回时回调用次函数,所以一般我们不去显示的调用。

ExitThread是推荐使用的结束一个线程的方法,当调用该函数时,当前线程的栈被释放,然后线程终止,相对于TerminateThread函数来说,这样做能够更好地完成附加在该线程上的DLL的清除工作. 但是ExitThread()会导致线程在清处构造器/自动变量之前就终止,所以我们最好不要显示的调用ExitThread()。

C++多线程(二)

C/C++ Runtime 多线程函数

一简单实例(来自codeprojct:

https://www.doczj.com/doc/678814526.html,/useritems/MultithreadingTutorial.asp)

主线程创建2个线程t1和t2,创建时2个线程就被挂起,后来调用ResumeThread恢复2个线程,是其开始执行,调用WaitForSingleObject等待2个线程执行完,然后推出主线程即结束进程。

/**//* file Main.cpp

*

* This program is an adaptation of the code Rex Jaeschke showed in

* Listing 1 of his Oct 2005 C/C++ User's Journal article entitled

* "C++/CLI Threading: Part I". I changed it from C++/CLI (managed)

* code to standard C++.

*

* One hassle is the fact that C++ must employ a free (C) function

* or a static class member function as the thread entry function.

*

* This program must be compiled with a multi-threaded C run-time

* (/MT for LIBCMT.LIB in a release build or /MTd for LIBCMTD.LIB

* in a debug build).

*

* John Kopplin 7/2006

*/

#include

#include // for STL string class

#include // for HANDLE

#include // for _beginthread()

using namespace std;

class ThreadX

{

private:

int loopStart;

int loopEnd;

int dispFrequency;

public:

string threadName;

ThreadX( int startValue, int endValue, int frequency )

{

loopStart = startValue;

loopEnd = endValue;

dispFrequency = frequency;

}

// In C++ you must employ a free (C) function or a static

// class member function as the thread entry-point-function.

// Furthermore, _beginthreadex() demands that the thread

// entry function signature take a single (void*) and returned

// an unsigned.

static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)

{

ThreadX * pthX = (ThreadX*)pThis; // the tricky cast

pthX->ThreadEntryPoint(); // now call the true entry-point-function

// A thread terminates automatically if it completes execution,

// or it can terminate itself with a call to _endthread().

return1; // the thread exit code

}

void ThreadEntryPoint()

{

// This is the desired entry-point-function but to get

// here we have to use a 2 step procedure involving

// the ThreadStaticEntryPoint() function.

for (int i = loopStart; i <= loopEnd; ++i)

{

if (i % dispFrequency == 0)

{

printf( "%s: i = %d\n", threadName.c_str(), i );

}

}

printf( "%s thread terminating\n", threadName.c_str() );

}

};

int main()

{

// All processes get a primary thread automatically. This primary

// thread can generate additional threads. In this program the

// primary thread creates 2 additional threads and all 3 threads

// then run simultaneously without any synchronization. No data

// is shared between the threads.

// We instantiate an object of the ThreadX class. Next we will

// create a thread and specify that the thread is to begin executing

// the function ThreadEntryPoint() on object o1. Once started,

// this thread will execute until that function terminates or

// until the overall process terminates.

ThreadX * o1 = new ThreadX( 0, 1, 2000 );

// When developing a multithreaded WIN32-based application with

// Visual C++, you need to use the CRT thread functions to create

// any threads that call CRT functions. Hence to create and terminate

// threads, use _beginthreadex() and _endthreadex() instead of

// the Win32 APIs CreateThread() and EndThread().

// The multithread library LIBCMT.LIB includes the _beginthread()

// and _endthread() functions. The _beginthread() function performs

// initialization without which many C run-time functions will fail.

// You must use _beginthread() instead of CreateThread() in C programs

// built with LIBCMT.LIB if you intend to call C run-time functions.

// Unlike the thread handle returned by _beginthread(), the thread handle

// returned by _beginthreadex() can be used with the synchronization APIs.

HANDLE hth1;

unsigned uiThread1ID;

hth1 = (HANDLE)_beginthreadex( NULL, // security

0, // stack size

ThreadX::ThreadStaticEntryPoint,

o1, // arg list

CREATE_SUSPENDED, // so we can later call ResumeThread()

&uiThread1ID );

if ( hth1 == 0 )

printf("Failed to create thread 1\n");

DWORD dwExitCode;

GetExitCodeThread( hth1, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259

printf( "initial thread 1 exit code = %u\n", dwExitCode );

// The System::Threading::Thread object in C++/CLI has a "Name" property.

// To create the equivalent functionality in C++ I added a public data member

// named threadName.

o1->threadName = "t1";

ThreadX * o2 = new ThreadX( -1000000, 0, 2000 );

HANDLE hth2;

unsigned uiThread2ID;

hth2 = (HANDLE)_beginthreadex( NULL, // security

0, // stack size

ThreadX::ThreadStaticEntryPoint,

o2, // arg list

CREATE_SUSPENDED, // so we can later call ResumeThread()

&uiThread2ID );

if ( hth2 == 0 )

printf("Failed to create thread 2\n");

GetExitCodeThread( hth2, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259

printf( "initial thread 2 exit code = %u\n", dwExitCode );

o2->threadName = "t2";

// If we hadn't specified CREATE_SUSPENDED in the call to _beginthreadex()

// we wouldn't now need to call ResumeThread().

ResumeThread( hth1 ); // serves the purpose of Jaeschke's t1->Start()

ResumeThread( hth2 );

// In C++/CLI the process continues until the last thread exits.

// That is, the thread's have independent lifetimes. Hence

// Jaeschke's original code was designed to show that the primary

// thread could exit and not influence the other threads.

// However in C++ the process terminates when the primary thread exits

// and when the process terminates all its threads are then terminated.

// Hence if you comment out the following waits, the non-primary

// threads will never get a chance to run.

WaitForSingleObject( hth1, INFINITE );

WaitForSingleObject( hth2, INFINITE );

GetExitCodeThread( hth1, &dwExitCode );

printf( "thread 1 exited with code %u\n", dwExitCode );

GetExitCodeThread( hth2, &dwExitCode );

printf( "thread 2 exited with code %u\n", dwExitCode );

// The handle returned by _beginthreadex() has to be closed

// by the caller of _beginthreadex().

CloseHandle( hth1 );

CloseHandle( hth2 );

delete o1;

o1 = NULL;

delete o2;

o2 = NULL;

printf("Primary thread terminating.\n");

}

二解释

1)如果你正在编写C/C++代码,决不应该调用CreateThread。相反,应该使用VisualC++运行期库函数_beginthreadex,推出也应该使用_endthreadex。如果不使用Microsoft的VisualC++编译器,你的编译器供应商有它自己的CreateThred替代函数。不管这个替代函数是什么,你都必须使用。

2)因为_beginthreadex和_endthreadex是CRT线程函数,所以必须注意编译选项runtimelibaray 的选择,使用MT或MTD。

3) _beginthreadex函数的参数列表与CreateThread函数的参数列表是相同的,但是参数名和类型并不完全相同。这是因为Microsoft的C/C++运行期库的开发小组认为,C/C++运行期函数不应该对Windows数据类型有任何依赖。_beginthreadex函数也像CreateThread那样,

返回新创建的线程的句柄。

下面是关于_beginthreadex的一些要点:

?每个线程均获得由C/C++运行期库的堆栈分配的自己的tiddata内存结构。(tiddata结构位于Mtdll.h文件中的VisualC++源代码中)。

?传递给_beginthreadex的线程函数的地址保存在tiddata内存块中。传递给该函数的参数也保存在该数据块中。

?_beginthreadex确实从内部调用CreateThread,因为这是操作系统了解如何创建新线程的唯一方法。

?当调用CreatetThread时,它被告知通过调用_threadstartex而不是pfnStartAddr来启动执行新线程。还有,传递给线程函数的参数是tiddata结构而不是pvParam的地址。

?如果一切顺利,就会像CreateThread那样返回线程句柄。如果任何操作失败了,便返回NULL。

4) _endthreadex的一些要点:

?C运行期库的_getptd函数内部调用操作系统的TlsGetValue函数,该函数负责检索调用线程的tiddata内存块的地址。

?然后该数据块被释放,而操作系统的ExitThread函数被调用,以便真正撤消该线程。当然,退出代码要正确地设置和传递。

5)虽然也提供了简化版的的_beginthread和_endthread,但是可控制性太差,所以一般不使用。

6)线程handle因为是内核对象,所以需要在最后closehandle。

7)更多的API:HANDLE GetCurrentProcess();HANDLE GetCurrentThread();DWORD GetCurrentProcessId();DWORD GetCurrentThreadId()。DWORD SetThreadIdealProcessor(HANDLE hThread,DWORD dwIdealProcessor);BOOL SetThreadPriority(HANDLE hThread,int nPriority);BOOL SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);BOOL GetThreadContext(HANDLE hThread,PCONTEXT pContext);BOOL SwitchToThread();

三注意

1)C++主线程的终止,同时也会终止所有主线程创建的子线程,不管子线程有没有执行完毕。所以上面的代码中如果不调用WaitForSingleObject,则2个子线程t1和t2可能并没有执行完毕或根本没有执行。

2)如果某线程挂起,然后有调用WaitForSingleObject等待该线程,就会导致死锁。所以上面的代码如果不调用resumethread,则会死锁。

C++多线程(三)

多线程同步之Critical Sections(功能与Mutex相同,保证某一时刻只有一个线程能够访问共享资源,但是不是内核对象,所以访问速度要比Mutex快,但是增没有等待超时的功能,所以有可能会导致死锁,使用时可以根据实际的情况选择其一)

一Critical Sections

1)因为Critical Sections不是内核对象,所以只能用来统一进程内线程间的同步,不能用来多个不同进程间的线程的同步。

2)如果在Critical Sections中间突然程序crash或是exit而没有调用LeaveCriticalSection,则结果是改线程所对应的内核不能被释放,该线程成为死线程。

3)要比其他的内核对象的速度要快。

二使用CriticalSections的简单实例,Stack在push的时候可以分为3个步骤,看下面的代码,但是如果在第2步后此线程中断切换到其他的线程,其他的线程push后再返回执行时,此线程继续执行,这样有可能刚才其他线程push就会被覆盖了,在stack里找不到了。(下面的代码在debug下使用了CriticalSection,release下可能有问题)

#include

#include

#include

/////////////////////////////////////////////

//stack:

struct Node

{

struct Node *next;

int data;

};

struct Stack

{

struct Node *head;

#ifdef _DEBUG

CRITICAL_SECTION critical_sec;

#endif

Stack()

{

head = NULL;

#ifdef _DEBUG

InitializeCriticalSection(&critical_sec); #endif

}

~Stack()

{

if(head != NULL)

{

if(NULL == head->next)

{

delete head;

head = NULL;

}

else

{

Node *p = head;

Node *q = head->next;

while(q != NULL)

{

delete p;

p = q;

q = q->next;

};

delete p;

p = NULL;

}

}

#ifdef _DEBUG

DeleteCriticalSection(&critical_sec);

#endif

}

void Push (int num)

{

//enter critical section, add a new node and then #ifdef _DEBUG

EnterCriticalSection (&critical_sec);

#endif

Node * node = new Node();

node->next = head;

node->data = num;

head = node;

printf("Stack:%d\n",num);

//leave critical section

#ifdef _DEBUG

LeaveCriticalSection (&critical_sec);

#endif

}

int Pop ()

{

#ifdef _DEBUG

EnterCriticalSection (&critical_sec); #endif

int result = 0;

if(head!= NULL)

{

result = head->data;

if(head->next != NULL)

{

Node *temp = head->next;

delete head;

head = temp;

}

else

head = NULL;

}

#ifdef _DEBUG

LeaveCriticalSection (&critical_sec); #endif

return result;

}

};

//////////////////////////////////////////////////////

//test:

unsigned __stdcall Thread1(void * pVoid) {

Stack *stack = ((Stack*)pVoid);

for(int i = 200; i<220;++i)

{

stack->Push(i);

}

return1;

}

unsigned __stdcall Thread2(void *pVoid)

{

Stack *stack = ((Stack*)pVoid);

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

{

stack->Push(i);

}

return1;

}

int main()

{

Stack stack;

stack.Push(1000);

stack.Push(1000);

HANDLE hth1;

unsigned uiThread1ID;

hth1 = (HANDLE)_beginthreadex( NULL, // security

0, // stack size

Thread1,

(void*)&stack, // arg list

CREATE_SUSPENDED, // so we can later call ResumeThread()

&uiThread1ID );

if ( hth1 == 0 )

printf("Failed to create thread 1\n");

DWORD dwExitCode;

GetExitCodeThread( hth1, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259

printf( "initial thread 1 exit code = %u\n", dwExitCode );

HANDLE hth2;

unsigned uiThread2ID;

hth2 = (HANDLE)_beginthreadex( NULL, // security

0, // stack size

Thread2,

(void*)&stack, // arg list

CREATE_SUSPENDED, // so we can later call ResumeThread()

&uiThread2ID );

if ( hth2 == 0 )

printf("Failed to create thread 2\n");

GetExitCodeThread( hth2, &dwExitCode ); // should be STILL_ACTIVE = 0x00000103 = 259

printf( "initial thread 2 exit code = %u\n", dwExitCode );

ResumeThread( hth1 );

ResumeThread( hth2 );

WaitForSingleObject( hth1, INFINITE );

WaitForSingleObject( hth2, INFINITE );

GetExitCodeThread( hth1, &dwExitCode );

printf( "thread 1 exited with code %u\n", dwExitCode );

GetExitCodeThread( hth2, &dwExitCode );

printf( "thread 2 exited with code %u\n", dwExitCode );

CloseHandle( hth1 );

CloseHandle( hth2 );

printf("Primary thread terminating.\n");

}

三对Critical Section的封装:

//////////////////////////////////////////////////////

// 方法一:Lock中的CritSect成员变量必须是引用类型。

class CritSect

{

public:

friend class Lock;

CritSect() { InitializeCriticalSection(&_critSection); }

~CritSect() { DeleteCriticalSection(&_critSection); } private:

void Acquire(){EnterCriticalSection(&_critSection);}

void Release(){LeaveCriticalSection(&_critSection);}

CRITICAL_SECTION _critSection;

};

class Lock

{

public:

Lock(CritSect& critSect):_critSect(critSect) { _critSect.Acquire(); }

~Lock(){_critSect.Release();}

private:

CritSect& _critSect;

};

//////////////////////////////////////////////////////

//方法二:

// MT-exclusive lock

class CLock {

public:

CLock() { InitializeCriticalSection (&m_criticalSection); }

void Lock () { EnterCriticalSection (&m_criticalSection); } void Unlock () { LeaveCriticalSection (&m_criticalSection); } virtual ~CLock() { DeleteCriticalSection (&m_criticalSection); } private:

CRITICAL_SECTION m_criticalSection;

// Scoped MT-exclusive lock

class CScopedLocker {

public:

CScopedLocker (CLock * t) : m_lock (t) { m_lock->Lock(); }

~CScopedLocker() { m_lock->Unlock(); }

private:

CLock * m_lock;

};

对上面的2中封装的调用都比较简单,都是只有2行代码。

CritSect sect;

Lock lock(sect);

CLock t;

CSCopedLocker st(&t);

下面的对封装的测试代码,保证了对g_n全局变量在线程1操作结束后线程2才可以操作。(下面的代码因为对全局变量同步,所以需要申明含有CRITICAL_SECTION的类为全局)#include

#include

using namespace std;

//////////////////////////////////////////////////////

// ???¨ò?£o

class CritSect

{

public:

friend class Lock;

CritSect() { InitializeCriticalSection(&_critSection); }

~CritSect() { DeleteCriticalSection(&_critSection); }

private:

void Acquire(){EnterCriticalSection(&_critSection);}

void Release(){LeaveCriticalSection(&_critSection);}

CRITICAL_SECTION _critSection;

};

class Lock

{

public:

Lock(CritSect& critSect):_critSect(critSect) { _critSect.Acquire(); } ~Lock(){_critSect.Release();}

private:

CritSect& _critSect;

};

//////////////////////////////////////////////////////

//???¨?t£o

Java多线程技术及案例

Java多线程技术及案例 进程和线程: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1–n个线程。 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。 线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。 多进程是指操作系统能同时运行多个任务(程序)。 多线程是指在同一程序中有多个顺序流在执行。 Java中多线程的多种实现方式 Java中有多种多线程实现方法,主要是继承https://www.doczj.com/doc/678814526.html,ng.Thread类的方法和 https://www.doczj.com/doc/678814526.html,ng.Runnable接口的方法。 继承Thread类 Thread是https://www.doczj.com/doc/678814526.html,ng包中的一个类,从这个类中实例化的对象代表线程,启动一个新线程需要建立一个Thread实例。 使用Thread类启动新的线程的步骤如下: 1.实例化Thread对象 2.调用start()方法启动线程 构造方法:

public Thread(String threadName); public Thread(); 例程: publicclass Thread1extends Thread{//定义一个类继承Thread privateint count=1000; publicvoid run(){//重写run方法 while(true){ System.out.print(count+" "); if(--count==0){ return; } } } publicstaticvoid main(String[] args){ Thread1 th1=new Thread1();//实例化继承了Thread的类 Thread1 th2=new Thread1(); th1.start();//调用start()方法, th2.start(); for(int i=0;i<1000;i++){ System.out.print("A "); } }

java多线程实现调度

重庆交通大学综合性设计性实验报告 实验项目名称:进程调度(先来先服务) 实验项目性质: JAVA多线程 实验所属课程: JAVA程序设计 实验室(中心):语音大楼 8 楼 801 班级:软件专业 2012级2班 姓名:尚亚* 学号: 631206050216 指导教师:杨 实验完成时间: 2014 年 11 月 25 日

一、实验目的 1、理解程序、线程和进程的概念; 2、理解多线程的概念; 3、掌握线程的各种状态; 4、熟练使用Thread类创建线程; 5、熟练使用线程各种方法; 6、掌握线程的调度及线程同步的实现原理。 二、实验内容及要求 进程调度是处理机管理的核心内容。本实验要求采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法编写和调试一个简单的进程调度程序。通过本实验可以加深理解有关进程控制块、进程队列的概念。并体会了优先数和先来先服务调度算法的具体实施办法。 用JA V A语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解。做一个能够直观体现多个进程时,CPU 是怎样调度就绪队列中的进程(按照先来先服务的原则)。

三、实验设备 PC机,windows7,eclipse。 四、设计方案 ㈠设计主要思想 (1)要模拟进程的调度算法,必须先体现处进程及系统资源。 (2)要体现先来先服务的算法,就必须表现出当有一个进程进入CPU时其他进程不能进入,并在就绪队列中排队。本实验建立了四个圆移动的线程表示作业调度,用圆在表示就绪队列的方框中停留表示进程在就绪队列中排队。 (3)当有一个圆移动到表示CPU的范围内时,让其它线程在就绪队列中排队,当CPU内无进程时,先来的圆先移动,以表示CPU 对进程的调度。 ㈡设计的主要步骤 (1)建立四个不同颜色的圆移动的线程,表示对四个进程的调度。 (2)当有一个表示进程的圆到达表示CPU范围内时,通过让其它几个圆停留在表示就绪队列的方框范围内,表示进程在就绪队列中排成队列。 (3)当第一个先到达的进程释放CPU,在排成队列的几个圆中选择先到达的圆,使其移动表示对先来的进程进行调度,直到所有的圆移动完毕。 五、主要代码 import java.awt.Font; import java.awt.event.*;

Java第七单元练习题Java多线程机制

J a v a第七单元练习题 J a v a多线程机制 The latest revision on November 22, 2020

7Java多线程机制 7.1单项选择题 1. 线程调用了sleep()方法后,该线程将进入()状态。 A. 可运行状态 B. 运行状态 C. 阻塞状态 D. 终止状态 2. 关于java线程,下面说法错误的是() A. 线程是以CPU为主体的行为 B. java利用线程使整个系统成为异步 C. 创建线程的方法有两种:实现Runnable接口和继承Thread类 D. 新线程一旦被创建,它将自动开始运行 3. 在java中的线程模型包含() A. 一个虚拟处理器 B. CPU执行的代码 C. 代码操作的数据 D. 以上都是 4.在java语言中,临界区可以是一个语句块,或者是一个方法,并用()关键字标识。 A. synchronized B. include C. import D. Thread 5. 线程控制方法中,yield()的作用是() A. 返回当前线程的引用 B. 使比其低的优先级线程执行 C. 强行终止线程 D. 只让给同优先级线程运行 6. 线程同步中,对象的锁在()情况下持有线程返回 A. 当synchronized()语句块执行完后 B. 当在synchronized()语句块执行中出现例外(exception)时 C. 当持有锁的线程调用该对象的wait()方法时 D. 以上都是 7. 在以下()情况下,线程就进入可运行状态 A. 线程调用了sleep()方法时 B. 线程调用了join()方法时 C. 线程调用了yield()方法时 D. 以上都是 8. java用()机制实现了进程之间的异步执行

第二章多线程分布式计算课后答案

第二章 1. 选择题 12345678910 D A B C C E C A B B 1112131415161718 B B B C A D A A 2. 程序/方法与进程/线程有什么不同?(53页第四段) 答:一个程序/方法是由程序员写的一段代码,它是静态的。进程/线程是由执行的程序/方法、当前值、状态信息和用于支持它执行的资源构成,资源是它执行时的动态因素。换言之,一个进程/线程是一个动态实体,只有当程序或函数执行时才会存在。 3. 比较多进程(多任务)操作系统和多线程编程环境。(53页5、 6、7段) 答:为了真正并行执行多个进程/线程,必须存在多个处理器。如果系统中只有一个处理器,表面上多个进程/线程执行,实际上实在分时模式下顺序执行。 从同一代码块可以创建多个进程/线程。默认情况下,包含在不同进程/线程中的代码和数据是分离的,每一个都有它自己执行代码的副本、局部变量的栈、对象数据区以及其他数据元素。 通常情况下,一个分布式操作系统可以由不同电脑上的多个实例或副本构成,每一个实例或副本都可以管理多个进程。同样,每个进程可以是由多个线程组成的一个多线程程序。 4. 什么是临界操作?用什么方法可以来保护临界操作?(54页第1 段) 答:对共享资源的访问称为临界操作。虽然一个简单的锁定可以防止共享资源被访问,但是也消除了并行处理的可能性。更理想的方法是不锁定并行读操作,而锁定并行读-写和写-写组合。 5. 什么是死锁?哪些策略可以用来解决死锁问题?(55页) 答:死锁的情况是两个或多个竞争操作等待对方完成,导致都不能完成。 解决方法: (1) 死锁预防:使用一种算法可以保证不会发生死锁。 (2) 死锁避免:使用一种算法,能够遇见死锁的发生从而拒绝资源请求、

Java多线程和网络编程项目

Megan package MultiTCP; import java.io.DataOutputStream; import java.io.IOException; import https://www.doczj.com/doc/678814526.html,.ServerSocket; import https://www.doczj.com/doc/678814526.html,.Socket; /** * 必须先启动再连接 * 1、创建服务器指定端口ServerSocket(int port) * 2、接收客户端的连接阻塞式 * 3、发送数据+接收数据 * * 接收多个客户端 */ @SuppressWarnings("all") public class MultiServer { public static void main(String[] args) throws IOException { //1、创建服务器指定端口 ServerSocket server = new ServerSocket(8888); while(true)//死循环一个accept 一个客户端 { //2、接收客户端的连接 Socket socket = server.accept(); System.out.println("一个客户端建立连接"); //2、发送数据 String msg = "欢迎使用"; //3、输出流 /*BufferedWriter bw = new BufferedWriter( new OutputStreamWriter( socket.getOutputStream())); bw.write(msg); bw.newLine();//一定要加行结束符,不然读不到数据 bw.flush();*/ DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); dos.writeUTF(msg); dos.flush(); } } } package MultiTCP; import java.io.DataInputStream;

java多线程并发面试题【java多线程和并发基础面试题】

java多线程并发面试题【java多线程和并 发基础面试题】 多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。下面就由小编为大家介绍一下java多线程和并发基础面试题的文章,欢迎阅读。 java多线程和并发基础面试题篇1 1. 进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用。而线程是在进程中执行的一个任务。Java运行环境是一个包含了不同的类和程序的单一进程。线程可以被称为轻量级进程。线程需要较少的来创建和驻留在进程中,并且可以共享进程中的。 2. 多线程编程的好处是什么? 在多线程程序中,多个线程被并发的执行以提高程序的效率,CPU不会因为某个线程需要等待而进入空闲状态。多个线程共享堆内存(heap memory),因此创建多个线程去执行一些任务会比创建多个进程更好。举个例子,Servlets比CGI更好,是因为Servlets支持多线程而CGI不支持。 3. 用户线程和守护线程有什么区别? 当我们在Java程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止JVM终止的

线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。 4. 我们如何创建一个线程? 有两种创建线程的方法:一是实现Runnable接口,然后将它传递给Thread的构造函数,创建一个Thread对象;二是直接继承Thread类。 java多线程和并发基础面试题篇2 1. 有哪些不同的线程生命周期? 当我们在Java程序中新建一个线程时,它的状态是New。当我们调用线程的start()方法时,状态被改变为Runnable。线程调度器会为Runnable线程池中的线程分配CPU时间并且讲它们的状态改变为Running。其他的线程状态还有Waiting,Blocked 和Dead。 2. 可以直接调用Thread类的run()方法么? 当然可以,但是如果我们调用了Thread的run()方法,它的行为就会和普通的方法一样,为了在新的线程中执行我们的代码,必须使用Thread.start()方法。 3. 如何让正在运行的线程暂停一段时间? 我们可以使用Thread类的Sleep()方法让线程暂停一段时间。需要注意的是,这并不会让线程终止,一旦从休眠中唤醒线程,线程的状态将会被改变为Runnable,并且根据线程调度,它将得到执行。

第十三章-多线程

第十三章Java多线程 学习目标 正确理解多线程概念 能够区分线程与进程的区别 掌握Java中创建线程的两种方式 理解线程优先级和死锁的概念 掌握线程的同步和通信 课前准备

13.1 本章简介 在Java中创建线程,实现使用线程的同步和通信,完成邮件的收发。 13.2相关实践知识 1.在MyEclipse 中新建名为MailBox 的项目,实现一个多线程的例子,在项目中新建mailbox 包。如(图13.1) 图13.1 2.在项目中新建类MailBox,用来存储邮件对象。为了简便,我们设置邮件的容量为1,即只能放一封信,发信者等待收信者取走信件后,才可以放入新邮件,代码如下:package mailbox; public class MailBox { private boolean newMail; // 是否有新的邮件 private String text; // 邮件内容 // 判断是否有新的邮件 public boolean isNewMail() { return newMail; } // 取走邮件 public String getText() { this.newMail = false; return text; } // 放置邮件 public void setText(String text) { this.newMail = true; this.text = text;

} } 3.在项目中新建Sender类,用来定义发信者,发送邮件到邮箱,代码如下, package mailbox; import java.text.SimpleDateFormat; import java.util.Date; public class Sender implements Runnable{ private MailBox mailBox; //初始邮箱 public Sender(MailBox mailBox){ this.mailBox = mailBox; } public void run() { try { while(true){ synchronized (mailBox){ while(mailBox.isNewMail()) // 邮件还未取走,线程等待 { mailBox.wait(); } // 给邮件添加时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss"); String str = "邮件内容:"; str += sdf.format(new Date()) + "/n"; str += "欢迎使用MailBox邮件系统!!"; mailBox.setText(str); //设定邮件内容 Thread.sleep(1000); // 模拟发送处理时间 mailBox.notify(); //通知收信者有新邮件 } } } catch (InterruptedException e) { e.printStackTrace(); } } } 4.在项目中新建类Receiver,用来定义收信者,从邮箱取出邮件,代码如下: package mailbox; public class Receiver extends Thread { private MailBox mailBox; // 初始邮箱 public Receiver(MailBox mailBox) { this.mailBox = mailBox; } @Override

JAVA多线程(一)基本概念和上下文切换性能损耗

JAVA多线程(一)基本概念和上下文切换性能损耗 1 多线程概念 在理解多线程之前,我们先搞清楚什么是线程。根据维基百科的描述,线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是行程中的实际运行单位。一条线程指的是进程中一个单一顺序的控制流,一個进程中可以并行多个线程,每条线程并行执行不同的任务。每个线程共享堆空间,拥有自己独立的栈空间。 这里反复出现的概念是线程和进程,我们在这里列出它们的区别: 线程划分尺度小于进程,线程隶属于某个进程; 进程是CPU、内存等资源占用的基本单位,线程是不能独立占有这些资源的; 进程之间相互独立,通信比较困难,而线程之间共享一块内存区域,通信方便; 进程在执行过程中,包含比较固定的入口、执行顺序和出口,而进程的这些过程会被应用程序控制。 多线程是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时

间执行多个线程,进而提升整体处理效能。 2 为什么要使用多线程 随着计算机硬件的发展,多核CPU已经屡见不鲜了,甚至手机处理器都早已是多核的天下。这就给我们使用多线程提供了硬件基础,但是,只是因为硬件让我们可以实现多线程,就要这样做吗?一起来看看多线程的优点: 更高的运行效率。在多核CPU上,线程之间是互相独立的,不用互相等待,也就是所谓的“并行“。举个例子,一个使用多线程的文件系统可以实现高吞吐量和低延迟。这是因为我们可以用一个线程来检索存储在高速介质(例如高速缓冲存储器)中的数据,另一个线程检索低速介质(例如外部存储)中的数据,二者互不干扰,也不用等到另一个线程结束才执行; 多线程是模块化的编程模型。在单线程中,如果主执行线程在一个耗时较长的任务上卡住,或者因为网络响应问题陷入长时间等待,此时程序不会响应鼠标和键盘等操作。多线程通过将程序分成几个功能相对独立的模块,单独分配一个线程去执行这个长耗时任务,不影响其它线程的执行,就可以避免这个问题; 与进程相比,线程的创建和切换开销更小。使用多线程为多个客户端服务,比使用多进程消耗的资源少得多。由于启动

1774143105-张强第5章第11次 多线程实验报告

第五章多线程 实验5-1 继承Thread类创建多线程 一、实验描述 1、考核知识点 名称:继承Thread类创建多线程 2、练习目标 掌握如何通过继承Thread类实现多线程的创建。 掌握Thread类中run()方法和start()方法的使用。 3、需求分析 在程序开发中,会遇到一个功能需要多个线程同时执行才能完成的情况。这时,可以通过继承线程类Thread,并重写Thread类中的run()方法来实现。为了让初学者熟悉如何创建多线程,在实验中将通过继承Thread类方式创建线程,并实现多线程分别打印0~99的数字的功能。 4、设计思路(实现原理) 1)自定义一个类Demo,使其继承Thread类。 2)在Demo类中重写run()方法,在run()方法内编写一个for循环,循环体内打印:“Demo:”+ 当前循环次数。 3)编写测试类Example01,在Example01类的main()方法中,创建一个Demo对象,并执行其 start()方法,接着编写一个for循环,循环体内打印:“main:”+当前循环次数。 二、实验实现 class Demo extends Thread { public void run() { for (int x = 0; x < 100; x++) { System.out.println("Demo:"+x); } } } public class Example01{ public static void main(String[] args) { Demo d = new Demo(); d.start(); for(int x=0; x<100; x++){ System.out.println("main:"+x); } }

Java线程总结

Java线程总结 在论坛上面常常看到初学者对线程的无可奈何,所以总结出了下面一篇文章,希望对一些正在学习使用java线程的初学者有所帮助。 首先要理解线程首先需要了解一些基本的东西,我们现在所使用的大多数操作系统都属于多任务,分时操作系统。正是由于这种操作系统的出现才有了多线程这个概念。我们使用的w indows,linux就属于此列。什么是分时操作系统呢,通俗一点与就是可以同一时间执行多个程序的操作系统,在自己的电脑上面,你是不是一边听歌,一边聊天还一边看网页呢?但实际上,并不上c pu在同时执行这些程序,c pu只是将时间切割为时间片,然后将时间片分配给这些程序,获得时间片的程序开始执行,不等执行完毕,下个程序又获得时间片开始执行,这样多个程序轮流执行一段时间,由于现在c pu 的高速计算能力,给人的感觉就像是多个程序在同时执行一样。 一般可以在同一时间内执行多个程序的操作系统都有进程的概念。一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间,一组系统资源。在进程概念中,每一个进程的内部数据和状态都是完全独立的。因此可以想像创建并执行一个进程的系统开像是比较大的,所以线程出现了。在java中,程序通过流控制来执行程序流,程序中单个顺序的流控制称为线程,多线程则指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。(你可以将前面一句话的程序换成进程,进程是程序的一次执行过程,是系统运行程序的基本单位) 线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制;但与进程不同的是,同类的多个线程是共享一块内存空间和一组系统资源,而线程本身的数据通常只有微处理器的寄存器数据,以及一个供程序执行时使用的堆栈。所以系统在产生一个线程。或者在各个线程之间切换时,负担要比进程小的多,正因如此,线程也被称为轻负荷进程(light-w eight proc ess)。一个进程中可以包含多个线程。 多任务是指在一个系统中可以同时运行多个程序,即有多个独立运行的任务,每个任务对应一个进程,同进程一样,一个线程也有从创建,运行到消亡的过程,称为线程的生命周期。用线程的状态(state)表明线程处在生命周期的哪个阶段。线程有创建,可运行,运行中,阻塞,死亡五中状态.通过线程的控制与调度可使线程在这几种状态间转化每个程序至少自动拥有一个线程,称为主线程。当程序加载到内存时,启动主线程。 [线程的运行机制以及调度模型] java中多线程就是一个类或一个程序执行或管理多个线程执行任务的能力,每个线程可以独立于其他线程而独立运行,当然也可以和其他线程协同运行,一个类控制着它的所有线程,可以决定哪个线程得到优先级,哪个线程可以访问其他类的资源,哪个线程开始执行,哪个保持休眠状态。 下面是线程的机制图: 线程的状态表示线程正在进行的活动以及在此时间段内所能完成的任务.线程有创建,可运行,运行中,阻塞,死亡五中状态。一个具有生命的线程,总是处于这五种状态之一: 1.创建状态 使用new运算符创建一个线程后,该线程仅仅是一个空对象,系统没有分配资源,称该线程处于创建状态(new thread) 2.可运行状态

JAVA多线程编程技术

JAVA多线程编程技术 第1章基础和使用 1.1多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念。 进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 什么是多线程呢?即就是一个程序中有多个线程在同时执行。 通过下图来区别单线程程序与多线程程序的不同: ●单线程程序:即,若有多个任务只能依次执行。当上一个任务执行结束后,下一个任务开 始执行。如,去网吧上网,网吧只能让一个人上网,当这个人下机后,下一个人才能上网。 ●多线程程序:即,若有多个任务可以同时执行。如,去网吧上网,网吧能够让多个人同时 上网。 1.2程序运行原理 ●分时调度 所有线程轮流使用CPU 的使用权,平均分配每个线程占用CPU 的时间。 ●抢占式调度 优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性),Java使用的为抢占式调度。 1.2.1抢占式调度详解 大部分操作系统都支持多进程并发运行,现在的操作系统几乎都支持同时运行多个程序。比如:现在我们上课一边使用编辑器,一边使用录屏软件,同时还开着画图板,dos窗口等软件。此时,这些程序是在同时运行,”感觉这些软件好像在同一时刻运行着“。 实际上,CPU(中央处理器)使用抢占式调度模式在多个线程间进行着高速的切换。对于CPU的一个核而言,某个时刻,只能执行一个线程,而CPU的在多个线程间切换速度相对我们的感觉要快,看上去就是在同一时刻运行。 其实,多线程程序并不能提高程序的运行速度,但能够提高程序运行效率,让CPU的使用率更高。

第02章 进程与线程习题解答

第2章进程与线程 习题2 参考解答 1. 简要回答下列问题。 1) 进程和线程有什么区别? 2) 线程是如何创建的?怎样设置线程的优先级? 3) 前台线程和后台线程有什么区别?如何将一个线程设置为后台线程? 【解答】 1) 一个完整的进程拥有自己独立的内存空间和数据,但是同一个进程内的线程是共享内存空间和数据的。一个进程对应着一段程序,它是由一些在同一个程序里面独立的同时运行的线程组成的。线程有时也被称为并行运行在程序里的轻量级进程,这是因为它的运行依赖于进程提供的上下文环境,并且使用的是进程的资源。 在一个进程里,线程的调度有抢占式或者非抢占的模式。在抢占模式下,操作系统负责分配CPU时间给各个线程,一旦当前的线程使用完分配给自己的CPU时间,操作系统将决定下一个占用CPU时间的是哪一个线程。因此操作系统将定期的中断当前正在执行的线程,将CPU 分配给在等待队列的下一个线程。所以任何一个线程都不能独占CPU。每个线程占用CPU的时间取决于进程和操作系统。进程分配给每个线程的时间很短,以至于我们感觉所有的线程是同时执行的。 2) C#中创建线程的工作是通过使用System.Threading名称空间下的Thread类的构造方法来完成的,如创建一个线程实例输出字符“a”1000次。 Thread thread = new Thread(new ThreadStart(func1)); thread.Priority =ThreadPriority.Normal; thread.Start(); static void func1() { for(int i =0;i<1000;i++) { Console.WriteLine("a"); } } C#中System.Threading名称空间下的ThreadPriority枚举类定义了线程可能具有的所有优先级的值,优先级由高到低排序为:Highest,AboveNormal,Normal,BelowNormal,Lowest。可以通过访问线程的Priority属性来获取和设置其优先级。每个线程都具有分配给它的线程优先级。在公共语言运行库中创建的线程最初分配的优先级为ThreadPriority.Normal。在运行库以外创建的线程保留它们在进入托管环境之前具有的优先级。可以使用Thread.Priority属性获取或设置任何线程的优先级。 3) 前台线程和后台线程的区别是后台线程不会影响进程终止。属于某个进程的所有前台线程都终止后,公共语言运行库就会结束该进程,而且所有属于该进程的后台线程也都会立即停止,而不管后台工作是否完成。 1

第5章 多线程_补充案例

第五章补充案例 案例5-1继承Thread类创建多线程 一、案例描述 1、考核知识点 编号:00105002 名称:继承Thread类创建多线程 2、练习目标 掌握如何通过继承Thread类实现多线程的创建。 掌握Thread类中run()方法和start()方法的使用。 3、需求分析 在程序开发中,会遇到一个功能需要多个线程同时执行才能完成的情况。这时,可以通过继承线程类Thread,并重写Thread类中的run()方法来实现。为了让初学者熟悉如何创建多线程,在案例中将通过继承Thread类方式创建线程,并实现多线程分别打印0~99的数字的功能。 4、设计思路(实现原理) 1)自定义一个类Demo,使其继承Thread类。 2)在Demo类中重写run()方法,在run()方法内编写一个for循环,循环体内打印:“Demo:”+ 当前循环次数。 3)编写测试类Example01,在Example01类的main()方法中,创建一个Demo对象,并执行其 start()方法,接着编写一个for循环,循环体内打印:“main:”+当前循环次数。 二、案例实现 class Demo extends Thread { public void run() { for (int x = 0; x < 100; x++) { System.out.println("Demo:"+x); } } } public class Example01{ public static void main(String[] args) { Demo d = new Demo(); d.start(); for(int x=0; x<100; x++){ System.out.println("main:"+x); }

深入理解Java多线程核心知识:跳槽面试必备

深入理解-Java-多线程核心知识:跳槽面试必备

————————————————————————————————作者:————————————————————————————————日期: ?

深入理解Java 多线程核心知识:跳槽面试必备 多线程相对于其他Java 知识点来讲,有一定的学习门槛,并且了解起来比较费劲。在平时工作中如若使用不当会出现数据错乱、执行效率低(还不如单线程去运行)或者死锁程序挂掉等等问题,所以掌握了解多线程至关重要。 本文从基础概念开始到最后的并发模型由浅入深,讲解下线程方面的知识。 概念梳理 本节我将带大家了解多线程中几大基础概念。 并发与并行 并行,表示两个线程同时做事情。 并发,表示一会做这个事情,一会做另一个事情,存在着调度。单核CPU 不可能存在并行(微观上)。 临界区 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待。

阻塞与非阻塞 阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其它所有需要这个资源的线程就必须在这个临界区中进行等待,等待会导致线程挂起。这种情况就是阻塞。 此时,如果占用资源的线程一直不愿意释放资源,那么其它所有阻塞在这个临界区上的线程都不能工作。阻塞是指线程在操作系统层面被挂起。阻塞一般性能不好,需大约8万个时钟周期来做调度。 非阻塞则允许多个线程同时进入临界区。 死锁 死锁是进程死锁的简称,是指多个进程循环等待他方占有的资源而无限的僵持下去的局面。

JAVA多线程的实验报告-

深圳大学实验报告课程名称:Java程序设计 实验项目名称:线程 学院:计算机与软件学院 专业: 指导教师:谭舜泉 报告人:学号:班级:3班 实验时间:2012年12月13日 实验报告提交时间:2012年12月26日 教务部制

一、实验内容: 8.2.3 吵醒休眠的线程 实验代码: class Shop implements Runnable { Thread zhangWorker,wangWorker,boss; Shop() { boss=new Thread(this);//创建boss,Shop对象为boss目标对象 zhangWorker=new Thread(this); wangWorker=new Thread(this); zhangWorker.setName("张工"); wangWorker.setName("王工"); boss.setName("老板"); } public void run() { int i=0; if(Thread.currentThread()==zhangWorker) { while(true) { try {i++; System.out.printf("\n%s已搬运了%d箱苹果 \n",zhangWorker.getName(),i); if(i==3)return; Thread.sleep(10000); }//zhangWorker休眠10秒} catch(InterruptedException e){System.out.printf("\n%s 让%s继续工作",boss.getName(),zhangWorker.getName());} } } else if(Thread.currentThread()==wangWorker) { while(true) { try

Java线程及多线程技术及应用

第6 章 Java线程及多线程技术及应用6.1线程基本概念 1、进程和线程的基础知识 ●进程:运行中的应用程序称为进程,拥有系统资源(cpu、内存) ●线程:进程中的一段代码,一个进程中可以哦有多段代码。本身不拥有资源(共享 所在进程的资源) 在java中,程序入口被自动创建为主线程,在主线程中可以创建多个子线程。 区别:1、是否占有资源问题 2、创建或撤销一个进程所需要的开销比创建或撤销一个线程所需要的开销大。 3、进程为重量级组件,线程为轻量级组件 ●多进程: 在操作系统中能同时运行多个任务(程序) ●多线程: 在同一应用程序中有多个功能流同时执行 2、线程的主要特点 ●不能以一个文件名的方式独立存在在磁盘中; ●不能单独执行,只有在进程启动后才可启动; ●线程可以共享进程相同的内存(代码与数据)。 3、线程的主要用途 ●利用它可以完成重复性的工作(如实现动画、声音等的播放)。 ●从事一次性较费时的初始化工作(如网络连接、声音数据文件的加载)。 ●并发执行的运行效果(一个进程多个线程)以实现更复杂的功能 4、多线程(多个线程同时运行)程序的主要优点 ●可以减轻系统性能方面的瓶颈,因为可以并行操作; ●提高CPU的处理器的效率,在多线程中,通过优先级管理,可以使重要的程序优先 操作,提高了任务管理的灵活性;另一方面,在多CPU系统中,可以把不同的线程 在不同的CPU中执行,真正做到同时处理多任务。 6.2 线程创建与启动 1、与线程编程有关的一些概念 创建方式: 1 继承https://www.doczj.com/doc/678814526.html,ng.Thread类 2 实现https://www.doczj.com/doc/678814526.html,ng.Runnable接口 线程体:public void run()方法,其内的程序代码决定了线程的行为和功能。 线程启动:public void start () , 线程启动后,需要获取cpu才能自动调用run()运行。线程休眠:public void sleep(long ms), 线程将暂停,放弃cpu

java多线程编程

第11章多线程编程 和其他多数计算机语言不同,Java内置支持多线程编程(multithreaded programming。多线程程序包含两条或两条以上并发运行的部分。程序中每个这样的部分都叫一个线程(thread),每个线程都有独立的执行路径。因此,多线程是多任务处理的一种特殊形式。 你一定知道多任务处理,因为它实际上被所有的现代操作系统所支持。然而,多任务处理有两种截然不同的类型:基于进程的和基于线程的。认识两者的不同是十分重要的。对很多读者,基于进程的多任务处理是更熟悉的形式。进程(process)本质上是一个执行的程序。因此,基于进程(process-based) 的多任务处理的特点是允许你的计算机同时运行两个或更多的程序。举例来说,基于进程的多任务处理使你在运用文本编辑器的时候可以同时运行Java编译器。在基于进程的多任务处理中,程序是调度程序所分派的最小代码单位。 在基于线程(thread-based) 的多任务处理环境中,线程是最小的执行单位。这意味着一个程序可以同时执行两个或者多个任务的功能。例如,一个文本编辑器可以在打印的同时格式化文本。所以,多进程程序处理“大图片”,而多线程程序处理细节问题。 多线程程序比多进程程序需要更少的管理费用。进程是重量级的任务,需要分配它们自己独立的地址空间。进程间通信是昂贵和受限的。进程间的转换也是很需要花费的。另一方面,线程是轻量级的选手。它们共享相同的地址空间并且共同分享同一个进程。线程间通信是便宜的,线程间的转换也是低成本的。当Java程序使用多进程任务处理环境时,多进程程序不受Java的控制,而多线程则受Java控制。 多线程帮助你写出CPU最大利用率的高效程序,因为空闲时间保持最低。这对Java运行的交互式的网络互连环境是至关重要的,因为空闲时间是公共的。举个例子来说,网络的数据传输速率远低于计算机处理能力,本地文件系统资源的读写速度远低于CPU的处理能力,当然,用户输入也比计算机慢很多。在传统的单线程环境中,你的程序必须等待每一个这样的任务完成以后才能执行下一步——尽管CPU有很多空闲时间。多线程使你能够获得并充分利用这些空闲时间。 如果你在Windows 98 或Windows 2000这样的操作系统下有编程经验,那么你已经熟悉了多线程。然而,Java管理线程使多线程处理尤其方便,因为很多细节对你来说是易于处理的。 11.1 Java线程模型 Java运行系统在很多方面依赖于线程,所有的类库设计都考虑到多线程。实际上,Java 使用线程来使整个环境异步。这有利于通过防止CPU循环的浪费来减少无效部分。 为更好的理解多线程环境的优势可以将它与它的对照物相比较。单线程系统的处理途径是使用一种叫作轮询的事件循环方法。在该模型中,单线程控制在一无限循环中运行,

相关主题
文本预览
相关文档 最新文档