![苏州培训java好吗 苏州培训java好吗](https://img.thea.cn/thea/images/contentpic/17/116.png)
java入门要注意什么
学习java就像是一个种花的过程,不断地为其施肥浇水,它才会茁壮成长。 而我们学习java,就要不断的充实自己、提升自己,才能获得更多机会。很多开始学习java编程的小白,经常就会被概念、定义什么的搞糊涂。当分类 、对象、接口、构造函数等等各种专业名词出现的时候,你一定是脑子里好像一片空白,根本就搞不懂这些字眼的意思和关系,而且,这种情况下,很 容易导致你丧失自信心,开始逃避、拒绝,这些小白经常遇到的情况在我刚接触java的时候也遇见了,但是好在我足够幸运,遇见了诚筑说。我现在已 经是公司的项目经理了,今天,我为大家来总结了一些经验和建议,希望能够帮助到大家。
一点:熟练基本的j2seAPI
除去java语言本身的语法之外呢,要懂得并且熟练j2seAPI的API也是非常有 必要的,在这里,就建议大家首先去掌握字符串的处理、异常的处理、容器、输入输出、线程等,这些相对来说较为重要的。还有就是API的内容是非 常庞大的,关于API,一定要懂得查询API的文件说明,在了解了其作用用途或者目的才能够进行相对于的程序。
二点:稳固java的语法基础
学习java一定要学会使用java的程序语言,用来编写程序,但是学习程序语 言就要熟悉语法是怎么使用的。程序语言其实也是一种语言,不过跟人类的语言不同,这种语言是要和计算机沟通交流,那怎么做才能熟悉这种语言呢 ,我给出的建议是多看别人写的程序,了解人家是怎么用java来解决问题的。然后再找类似的程序去练习了,这样就能够从实际操作中检验自己是否真 的知道该怎么去解决问题了。
三点:加入贴吧论坛多参与讨论
根据我当时的经验,在大家学习的过程中,如果有人可以参与话题,共同讨 论的话,会加快你学习的速度。所以大家可以和我一样,找一个技术讨论的地方,贴吧啊,论坛啊都可以,在这里进行讨论,毕竟大家有着共同的目标 和理想,有着共同的话题可聊,这样的话,又大大节省了学习的时间。
学完基本的java语法呢,现在就该用java来进行实际的编程了,假如你需要 编写窗口程序,那就学Swing窗口设计;假如你要编写数据库什么的,那就学JDBC等等。
java互联网开发工程师
关于mfc线程 的退出问题、同步问题
>AfxBeginThread()函数的返回值是CWinThread* 指针,但是这个指针不能直接使用,因为这个指针会自动销毁。如果道友直接使用了这个指针,那么当在操作这个指针时,若已被mfc销毁,那么访问违规将会到来。 至于返回值的使用请看,我写的一个mfc程序片段。 [html] view plain copy CString strName = _T(""); CWinThread* pThread = NULL; UINT CBcgTestDlg::ThreadWorkFunc(LPVOID lPvoid) { for (int n = 0; n < 10000; n ) { strName = _T("http://blog.csdn.net/windows_nt"); strName = strName _T("\n"); TRACE(strName); } return 0; } void CBcgTestDlg::OnOK() { for (int n = 0; n < 10000; n) { if (pThread) { WaitForSingleObject(pThread->m_hThread, INFINITE); delete pThread; } pThread = AfxBeginThread(ThreadWorkFunc, NULL, 0, CREATE_SUSPENDED, NULL); if (pThread) { pThread->m_bAutoDelete = FALSE; pThread->ResumeThread(); } } }
接下来我主要讲一下自己在学习windows核心编程中对于临界区线程同步方式的使用。
临界区线程同步在windows核心编程中被称为关键段线程同步,以下统称关键段 关键段是一小段代码,它在执行之前需要独占对一些资源的访问权。 缺点:能且只能用在一个进程中的多线程同步。可能陷入死锁,因为我们无法为进入关键段的线程设置**大等待时间。 接下来我介绍一些关键段线程同步的使用 先看一个事例代码
Slim读/写锁
SRWLock允许我们区分那些想要读取资源的值的线程(读取者线程)和想要更新资源的值的线程(写入者线程)。 [html] view plain copy //1、首先我们要分配一个SRWLOCK对象并用下边函数初始化它。 void InitializeSRWLock( __out PSRWLOCK SRWLock ) //2、请求对保护资源的独占访问权(写权限) void AcquireSRWLockExclusive( __inout PSRWLOCK SRWLock ) //3、完成对资源的更新后,应该解除对资源的锁定 void ReleaseSRWLockExclusive( __inout PSRWLOCK SRWLock ) //4、对应的读者线程函数如下 void AcquireSRWLockShared( __inout PSRWLOCK SRWLock ) void ReleaseSRWLockShared( __inout PSRWLOCK SRWLock ) 与关键段相比,PSRWLOCK缺乏下面两个特性 1、不存在TryEnter(Share/Exclusive)SRWLock之类的函数,如果锁已经被占用,那么调用会阻塞调用线程 2、不能递归的获得PSRWLOCK。也就是说,一个线程不能为了多次写入资源而多次锁定资源,如后再多次释放对资源的锁定。 线程同步性能排序(由高到低) volatile读取 -->volatile写入-->Interlocked API(原子方式)-->SRWLock-->关键段-->内核对象 二、互斥器(Mutexes)的用途和临界区(critical section)的用途非常相似,如:一个时间内只能够有一个线程拥有mutex,就好像同一时间内只能够有一个线程进入同一个critical section一样。但是mutex**牺牲速度,提高了灵活性,功能变得更加强大了。 虽然mutex和critical section做相同的事情,但它们的运作还是有差别的: 1、锁住一个未被拥有的mutex,比锁住一个未被拥有的critical section需要花费几乎100倍的时间。 2、mutex可以跨进程使用。critical section则只能在同一个进程中使用。3、等待一个mutex时,你可以指定“结束等待”的世间长度,但对于critical section则不行。
以下是mutex和critical section的相关函数比较:
临界区 | 互斥器 |
CRITICAL_SECTION InitializeCriticalSection() | CreateMutex() OpenMutex() |
EnterCriticalSection() | WaitForSingleObject() WaitForMultipleObjects() MsgWaitForMultipleObjects() |
LeaveCriticalSection() | ReleaseMutex() |
DeleteCriticalSection() | CloseHandle() |
在一个适当的程序中,线程绝对不应该在它即将结束前还拥有一个mutex,因为这意味着线程没有能够适当地清除其资源。不幸的是,我们并不身处一个完美的世界,有时候,因为某种理由,线程可能没有在结束前调用ReleaseMutex()。为了解决这个问题,mutex有一个非常重要的特性。这性质在各种同步机制中是独一无二的,如果线程拥有一个mutex而在结束前没有调用ReleaseMutex(),mutex不会被摧毁,取而代之的是,该mutex会被视为“未被拥有”以及“未被激发”,而下一个等待中的线程会被以WAIT_ABANDONED_0通知。无论线程是因为ExitThread()而结束,或是因当掉而结束,这种情况都存在。
任何时候只要你想锁住超过一个以上的同步对象,你就有死锁的潜在病因。 如果总是在相同时间把所有对象都锁住,问题可去矣。 事例如下,存在潜在死锁的可能:
前边讲过了互斥器线程同步-----windows核心编程-互斥器(Mutexes),这章我来介绍一下信号量(semaphore)线程同步。
理论上说,mutex是semaphore的一种退化。如果你产生一个semaphore并令**大值为1,那就是一个mutex。也因此,mutex又常被称为binary semaphore。如果某个线程拥有一个binary semaphore,那么就没有其他线程能够获得其拥有权。但是在win32中,这两种东西的拥有权的意义完全不同,所以它们不能够交换使用,semaphore不像mutex,它并没有所谓的“wait abandoned”状态可以被其他线程侦测到。 每当一个锁定动作成功,semaphore的现值就会减1,你可以使用任何一种wait...()函数来要求锁定一个semaphore。如果semaphore的现值不为0,wait...()函数会立刻返回,这和mutex很像,当没有任何线程拥有mutex,wait...()函数会立刻返回。 注意,如果锁定成功,你也不会收到semaphore的拥有权。因为可以有一个以上的线程同时锁定一个semaphore。所以谈semaphore的拥有权并没有太多实际意义。在semaphore身上并没有所谓“独占锁定”这种事情。也因为没有所有权的观念,一个线程可以反复调用wait...()函数以产生新的锁定。这和mutex绝不相同:拥有mutex的线程不论再调用多少次wait...()函数,也不会被阻塞住。 与mutex不同的是,调用ReleaseSemaphore()的那个线程,并不一定就得是调用wait...()的那个线程。 任何线程都可以在任何时间调用ReleaseSemaphore(),解除被任何线程锁定的semaphore。
以下是我对三种同步方式中,常用到的函数的总结。
临界区 | 互斥器 | 信号量 |
CRITICAL_SECTION InitializeCriticalSection() | CreateMutex() OpenMutex() | CreateSemaphore |
EnterCriticalSection() | WaitForSingleObject() WaitForMultipleObjects() MsgWaitForMultipleObjects() | WaitForSingleObject() WaitForMultipleObjects() MsgWaitForMultipleObjects() ... |
LeaveCriticalSection() | ReleaseMutex() | ReleaseSemaphore() |
DeleteCriticalSection() | CloseHandle() | CloseHandle() |
事件线程同步----- window核心编程-内核对象线程同步
四、
上一章讲了关键字(临界区)线程同步,使用关键字线程同步,我们很容易陷入死锁的情形,这是因为我们无法为进入关键段指定一个**长等待时间。
本章将讨论如何使用内核对象来对线程同步。我们也将看到,与用户模式下的同步机制(关键段同步)相比,内核对象的用途要广泛的多。实际上,内核对象唯一的缺点就是它们的性能。内核对象包括进程、线程以及作业,几乎所有这些内核对象都可以用来进行同步。对线程同步来书,这些内核对象中的每一种要么处于触发状态,要么处于未触发状态。Microsoft为每种对象创建了一些规则,规定如何在这两种状态之间进行转换。例如,进程内核对象在创建的时候总是处于未触发状态。当进程终止的时候,操作系统会自动使进程内核对象变成触发状态。当进程内核对象被触发后,它将永远保持这种状态,再也不会变回到未触发状态。在进程内核对象的内部有一个布尔变量,当系统创建内核对象的时候会把这个变量的值初始化为false(未触发)。当进程终止的时候,操作系统会自动把相应的内核对象中的这个布尔值设为true,表示该对象已经被触发。
/*函数的返回值告诉调用方函数为什么它得以继续运行。如果给bWaitAll传的是FALSE,那么只要任何一个对象被触发,函数就会立即返回。这时的返回值是WAIT_OBJECT_0和(WAIT_OBJECT_0 dwCount-1)之间的任何一个值。换句话说,如果返回值既不是WAIT_TIMEOUT,也不是WAIT_FAILED,那么我们应该把返回值减去WAIT_OBJECT_0。得到的数值是我们在第二个参数中传的句柄数组的一个索引,用来告诉我们被触发的是那个对象。*/
//下面的事例代码可以更清晰的对此进行解释 [html] view plain copy HANDLE h[3];//我的博客:<a href="http://blog.csdn.net/windows_nt">http://blog.csdn.net/windows_nt</a> h[0] = hPRocess1; h[1] = hProcess2; h[2] = hProcess3; DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); switch(dw) { case WAIT_FAILED: //Bad call to function (invalid handle) break; case WAIT_TIMEOUT: //None of the objects became signaled within 5000 milliseconds break; case WAIT_OBJECT_0 0: //h[0] signaled, hProcess1 terminated break; case WAIT_OBJECT_0 1: //h[1] signaled, hProcess2 terminated break; case WAIT_OBJECT_0 2: //h[2] signaled, hProcess3 terminated break; }2、事件内核对象
//事件包含一个使用计数(这一点和所有其他内核对象一样),一个用来表示事件是自动重置事件还是手动重置事件的布尔值,以及另一个用来表示事件有没有被触发的布尔值。 //有两种不同类型的事件对象:手动重置事件和自动重置事件。当一个手动重置事件被触发的时候,正在等待该事件的所有线程都将变成可调度状态,而当一个自动重置事件被触发的时候,只有一个正在等待该事件的线程会变成可调用状态。 //创建一个事件内核对象 HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性 BOOL bManualReset, //自动重置/手动重置 BOOL bInitialState, //是否触发LPCSTR lpName );//事件内核对象的名字,可以为空
//新版本
HANDLE CreateEventEx( LPSECURITY_ATTRIBUTES psa, //安全属性 PCTSTR pszName, //名字 DWORD dwFlags, //是否触发DWORD dwDesiredaccess)
//dwDesiredAccess:允许我们指定在创建事件时返回的句柄对事件有何种访问权限。这是一种创建事件句柄的新方法,它可以减少权限,相比较而言,CreateEvent()总是被授予全部权限。但CreateEventEx()更有用的地方在于它允许我们以减少权限的方式来打开一个已经存在的事件,而CreateEvent()总是要求全部权限。
//下边这个例子展示了如何使用事件内核对象来对线程进行同步。 [html] view plain copy //Create a global handle to a manual-reset, nonsignaled event. HANDLE g_hEvent; int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { //Create the manual-reset, nonsignaled event g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //Spawn 3 new threads HANDLE hThread[3]; DWORD dwThread; hThread[0] = _beginthread(NULL, 0, wordCount, NULL, 0, &dwThread); hThread[1] = _beginthread(NULL, 0, SpellCheck, NULL, 0, &dwThread); hThread[2] = _beginthread(NULL, 0, GrammarCheck, NULL, 0, &dwThread); OpenFileAndReadContentsIntoMemory(...); //allow all 3 threads to access the memory SetEvent(g_hEvent); } DWORD WINAPI wordCount(PVOID pvParam) { //Wait until the file s data is in memory waitForSingleObject(g_hEvent, INFINITE); //access the memory block. return 0; } DWORD WINAPI SpellCheck(PVOID pvParam) { //Wait until the file s data is in memory waitForSingleObject(g_hEvent, INFINITE); //access the memory block. return 0; } DWORD WINAPI GrammarCheck(PVOID pvParam) { //Wait until the file s data is in memory waitForSingleObject(g_hEvent, INFINITE); //access the memory block. return 0; }下边是我自己写的一个事例片段,很简单
相关推荐: