热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java线程的深入探讨(转)

Java线程的深入探讨(转)[more]Java线程的深入探讨作者:不详文章来源:动网先锋1.什么是线程一般来说,我们把正在计算机中执行的程序叫做进程
Java线程的深入探讨 (转)[@more@]
Java线程的深入探讨

作者:不详

文章来源:动网先锋
 
1.什么是线程 

  一般来说,我们把正在计算机中执行的程序叫做"进程"(Process) ,而不将其 
称为程序(Program)。所谓"线程"(Thread),是"进程"中某个单一顺序的控制流。 
新兴的操作系统,如Mac,windows NT,Windows 95等,大多采用多线程的概念,把线 
程视为基本执行单位。线程也是Java中的相当重要的组成部分之一。 

  甚至最简单的Applet也是由多个线程来完成的。在Java中,任何一个Applet的 
paint()和update()方法都是由AWT(Abstract Window Toolkit)绘图与事件处理线 
程调用的,而Applet 主要的里程碑方法——init(),start(),stop()和destory() 
——是由执行该Applet的应用调用的。 

  单线程的概念没有什么新的地方,真正有趣的是在一个程序中同时使用多个线 
程来完成不同的任务。某些地方用轻量进程(Lightweig ht Process)来代替线程 
,线程与真正进程的相似性在于它们都是单一顺序控制流。然而线程被认为轻量是 
由于它运行于整个程序的上下文内,能使用整个程序共有的资源和程序环境。 

  作为单一顺序控制流,在运行的程序内线程必须拥有一些资源作为必要的开销 
。例如,必须有执行堆栈和程序计数器。在线程内执行的代码只在它的上下文中起 
作用,因此某些地方用"执行上下文"来代替"线程"。 

  2.线程属性 

  为了正确有效地使用线程,必须理解线程的各个方面并了解Java 实时系统。 
必须知道如何提供线程体、线程的生命周期、实时系统如 何调度线程、线程组、 
什么是幽灵线程(Demo nThread)。 

  (1)线程体 
  所有的操作都发生在线程体中,在Java中线程体是从Thread类继承的run()方 
法,或实现Runnable接口的类中的run()方法。当线程产生并初始化后,实时系统调 
用它的run()方法。run()方法内的代码实现所产生线程的行为,它是线程的主要部 
分。 

  (2)线程状态 
  附图表示了线程在它的生命周期内的任何时刻所能处的状态以及引起状态改 
变的方法。这图并不是完整的有限状态图,但基本概括了线程中比较感兴趣和普遍 
的方面。以下讨论有关线程生命周期以此为据。 


  ●新线程态(New Thread) 
  产生一个Thread对象就生成一个新线程。当线程处于"新线程"状态时,仅仅是 
一个空线程对象,它还没有分配到系统资源。因此只能启动或终止它。任何其他操 
作都会引发异常。 
  ●可运行态(Runnable) 
  start()方法产生运行线程所必须的资源,调度线程执行,并且调用线程的run 
()方法。在这时线程处于可运行态。该状态不称为运行态是因为这时的线程并不 
总是一直占用处理机。特别是对于只有一个处理机的PC而言,任何时刻只能有一个 
处于可运行态的线程占用处理 机。Java通过调度来实现多线程对处理机的共享。 

  ●非运行态(Not Runnable) 
  当以下事件发生时,线程进入非运行态。 
  ①suspend()方法被调用; 
  ②sleep()方法被调用; 
  ③线程使用wait()来等待条件变量; 
  ④线程处于I/O等待。 
  ●死亡态(Dead) 
  当run()方法返回,或别的线程调用stop()方法,线程进入死亡态 。通常Appl 
et使用它的stop()方法来终止它产生的所有线程。 

  (3)线程优先级 
  虽然我们说线程是并发运行的。然而事实常常并非如此。正如前面谈到的,当 
系统中只有一个cpu时,以某种顺序在单CPU情况下执行多线程被称为调度(schedu 
ling)。Java采用的是一种简单、固定的调度法,即固定优先级调度。这种算法是 
根据处于可运行态线程的相对优先级来实行调度。当线程产生时,它继承原线程的 
优先级。在需要时可对优先级进行修改。在任何时刻,如果有多条线程等待运行, 
系统选择优先级最高的可运行线程运行。只有当它停止、自动放弃、或由于某种 
原因成为非运行态低优先级的线程才能运行。如果两个线程具有相同的优先级,它 
们将被交替地运行。 
  Java实时系统的线程调度算法还是强制性的,在任何时刻,如果一个比其他线 
程优先级都高的线程的状态变为可运行态,实时系统将选择该线程来运行。 

  (4)幽灵线程 
  任何一个Java线程都能成为幽灵线程。它是作为运行于同一个进程内的对象 
和线程的服务提供者。例如,HotJava浏览器有一个称为" 后台图片阅读器"的幽灵 
线程,它为需要图片的对象和线程从文件系统或网络读入图片。 
  幽灵线程是应用中典型的独立线程。它为同一应用中的其他对象和线程提供 
服务。幽灵线程的run()方法一般都是无限循环,等待服务请求。 

  (5)线程组 
  每个Java线程都是某个线程组的成员。线程组提供一种机制,使得多个线程集 
于一个对象内,能对它们实行整体操作。譬如,你能用一个方法调用来启动或挂起 
组内的所有线程。Java线程组由ThreadGroup类实现。 
  当线程产生时,可以指定线程组或由实时系统将其放入某个缺省的线程组内。 
线程只能属于一个线程组,并且当线程产生后不能改变它所属的线程组。 

  3.多线程程序 

  对于多线程的好处这就不多说了。但是,它同样也带来了某些新的麻烦。只要 
在设计程序时特别小心留意,克服这些麻烦并不算太困难。 

  (1)同步线程 
  许多线程在执行中必须考虑与其他线程之间共享数据或协调执行状态。这就 
需要同步机制。在Java中每个对象都有一把锁与之对应。但Java不提供单独的lo 
ck和unlock操作。它由高层的结构隐式实现, 来保证操作的对应。(然而,我们注 
意到Java虚拟机提供单独的monito renter和monitorexit指令来实现lock和unlo 
ck操作。) 
  synchronized语句计算一个对象引用,试图对该对象完成锁操作, 并且在完成 
锁操作前停止处理。当锁操作完成synchronized语句体得到执行。当语句体执行 
完毕(无论正常或异常),解锁操作自动完成。作为面向对象的语言,synchronized 
经常与方法连用。一种比较好的办法是,如果某个变量由一个线程赋值并由别的线 
程引用或赋值,那么所有对该变量的访问都必须在某个synchromized语句或synch 
ronized方法内。 
  现在假设一种情况:线程1与线程2都要访问某个数据区,并且要求线程1的访 
问先于线程2, 则这时仅用synchronized是不能解决问题的。这在unix或Windows 
NT中可用Simaphore来实现。而Java并不提供。在Java中提供的是wait()和noti 
fy()机制。使用如下: 
  synchronized method-1(…){ call by thread 1. 
  ∥access data area; 
  available=true; 
  notify() 
  } 
  synchronized method-2(…){∥call by thread 2. 
  while(!available) 
  try{ 
  wait();∥wait for notify(). 
  }catch (Interrupted Exception e){ 
  } 
  ∥access data area 
  } 
  其中available是类成员变量,置初值为false。 
  如果在method-2中检查available为假,则调用wait()。wait()的作用是使线 
程2进入非运行态,并且解锁。在这种情况下,method-1可以被线程1调用。当执行 
notify()后。线程2由非运行态转变为可运行态。当method-1调用返回后。线程2 
可重新对该对象加锁,加锁成功后执行wait()返回后的指令。这种机制也能适用于 
其他更复杂的情况。 

  (2)死锁 
  如果程序中有几个竞争资源的并发线程,那么保证均衡是很重要的。系统均衡 
是指每个线程在执行过程中都能充分访问有限的资源。系统中没有饿死和死锁的 
线程。Java并不提供对死锁的检测机制。对大多数的Java程序员来说防止死锁是 
一种较好的选择。最简单的防止死锁的方法是对竞争的资源引入序号,如果一个线 
程需要几个资源,那么它必须先得到小序号的资源,再申请大序号的资源。 

  4.小结 

  线程是Java中的重要内容,多线程是Java的一个特点。虽然Java的同步互斥不 
如某些系统那么丰富,但适当地使用它们也能收到满意的效果。



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-988090/,如需转载,请注明出处,否则将追究法律责任。

转:http://blog.itpub.net/10752043/viewspace-988090/



推荐阅读
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 关于CMS收集器的知识介绍和优缺点分析
    本文介绍了CMS收集器的概念、运行过程和优缺点,并解释了垃圾回收器的作用和实践。CMS收集器是一种基于标记-清除算法的垃圾回收器,适用于互联网站和B/S系统等对响应速度和停顿时间有较高要求的应用。同时,还提供了其他垃圾回收器的参考资料。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
  • 本文介绍了Java虚拟机中的垃圾收集器,包括年轻代收集器Serial收集器、ParNew收集器、Parallel Scavenge收集器,以及老年代收集器Serial Old收集器、Parallel Old收集器和CMS收集器。对每种收集器的算法和特点进行了详细解析,希望对读者有参考价值。 ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • MySQL数据库锁机制及其应用(数据库锁的概念)
    本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
  • java drools5_Java Drools5.1 规则流基础【示例】(中)
    五、规则文件及规则流EduInfoRule.drl:packagemyrules;importsample.Employ;ruleBachelorruleflow-group ... [详细]
author-avatar
5jkd_330
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有