java线程介绍

从面向对象编程的角度来看:

第1种创建方式(创建Thread类的子类)是一种基于继承的技术,第2种创建方式(以Runnable接口实例为构造器参数直接通过new创建Thread实例)是一种基于组合(Composition)的技术。

由于组合相对继承来说,其类和类之间的耦合性(Coupling)更低,因此它也更加灵活。一般我们认为组合是优先选用的技术。

从对象共享的角度来看:

第2种创建方式意味着多个线程实例可以共享同一个Runnable实例。

从对象创建成本的角度来看:

Java中的线程实例是一个“特殊”的Runnable实例,因为在创建它的时候Java虚拟机会为其分配调用栈空间、内核线程等资源。因此,创建一个线程实例比起创建一个普通的Runnable实例来说,其成本要相对昂贵一点。所以,如果创建Runnable实例再将其作为方法参数传递给其他对象使用(JDK标准库中有不少API都使用了Runnable接口)而不必利用它来创建相应的线程(即第2种线程创建方式)即可满足我们的计算需要,那么就不要创建线程实例。

线程的属性:线程的编号(ID)、名称(Name)、线程类别(Daemon)和优先级(Priority)

属性属性类型及用途只读属性重要注意事项

编号(ID)

类型:long。

用于标识不同的线程。不同的线程拥有不同的编号

某个编号的线程运行结束后,该编号可能被后续创建的线程使用。不同线程拥有的编号虽然不同,但是这种编号的唯一性只在Java虚拟机的一次运行有效。也就是说重启一个Java虚拟机(如重启Web服务器)后,某些线程的编号可能与上次Java虚拟机运行的某个线程的编号一样,因此该属性的值不适合用作某种唯一标识,特别是作为数据库中的唯一标识(如主键)

名称(Name)

类型:String。

面向人(而非机器)的一个属性,用于区分不同的线程。默认值与线程的编号有关,默认值的格式为:“Thread-线程编号”,如“Thread-0”

Java并不禁止我们将不同的线程的名称属性设置为相同的值。尽管如此,设置线程的名称属性有助于代码调试和定位

线程类别(Daemon) 类型:boolean。

值为true表示相应的线程为守护线程,否则表示相应的线程为用户线程。该属性的默认值与相应线程的父线程的该属性的值相同

该属性必须在相应线程启动之前设置,即对setDaemon方法的调用必须在对start方法的调用之前,否则setDaemon方法会抛出IllegalThreadStateException异常。负责一些关键任务处理的线程不适宜设置为守护线程

优先级(Priority) 类型:int。

该属性本质上是给线程调度器的提示,用于表示应用程序希望哪个线程能够优先得以运行。Java定义了1~10的10个优先级。默认值一般为5(表示普通优先级)。对于具体的一个线程而言,其优先级的默认值与其父线程(创建该线程的线程)的优先级值相等

一般使用默认优先级即可。不恰当地设置该属性值可能导致严重的问题(线程饥饿)

Java线程的优先级属性本质上只是一个给线程调度器的提示信息,以便于线程调度器决定优先调度哪些线程运行。它并不能保证线程按照其优先级高低的顺序运行。注意,Java线程的优先级使用不当或者滥用则可能导致某些线程永远无法得到运行,即产生了线程饥饿(ThreadStarvation)。因此,线程的优先级并不是设置得越高越好;一般情况下使用普通优先级即可,即不必设置线程的优先级属性。按照线程是否会阻止Java虚拟机正常停止,我们可以将Java中的线程分为守护线程(DaemonThread)和用户线程(UserThread,也称非守护线程)。线程的daemon属性用于表示相应线程是否为守护线程。用户线程会阻止Java虚拟机的正常停止,即一个Java虚拟机只有在其所有用户线程都运行结束(即Thread.run()调用未结束)的情况下才能正常停止。而守护线程则不会影响Java虚拟机的正常停止,即应用程序中有守护线程在运行也不影响Java虚拟机的正常停止。因此,守护线程通常用于执行一些重要性不是很高的任务,例如用于监视其他线程的运行情况。

对线程进行监视的主要途径是获取并查看程序的线程转储(ThreadDump)。一个程序的线程转储包含了获取这个线程转储的那一刻该程序的线程信息。这些信息包括程序中有哪些线程以及这些线程的具体信息。

  • 进程是程序的运行实例,一个进程可以包含多个线程,这些线程共享其所在进程的资源。

  • 线程是进程中可独立执行的最小单位。Java标准库类java.lang.Thread就是Java平台对线程的实现。特定线程总是在执行特定的任务,线程的run方法就是线程所要执行任务的处理逻辑的入口方法,该方法由Java虚拟机直接调用执行。Java标准库接口java.lang.Runnable就是对任务的抽象,Thread类就是Runnable接口的一个实现类。

  • 应用程序负责线程的创建与启动,而线程调度器负责线程的调度和执行。Java平台中有两种方式创建线程:创建Thread的子类和以Runnable接口实例为构造器参数直接通过new创建Thread实例。

  • 在Java平台中,任何一段代码总是执行在确定的代码中的。同一段代码可以被不同的线程执行。代码可以通过Thread.currentThread()调用来获取其当前执行线程。

  • 为每个线程设置一个简短而含义明确的名称属性有助于多线程程序的调试和问题定位。

  • 一个线程从其创建到运行结束的整个生命周期会经历若干状态。线程执行过程中调用一些对象的方法(如Thread.sleep(longmillis))或者执行特定的操作(如I/O操作)往往导致其状态的变更。线程转储是对线程进行监视的重要媒介。操作系统以及JDK都提供了一些工具(jvisualvm、jstack和JavaMissionControl),可以用来获取线程转储。

  • Java平台是一个多线程的平台,线程的身影在Java平台中无处不在。按照线程间的创建关系,我们可以将多个线程间的关系理解为一个层次关系。Java并无相关API用于获取一个线程的父线程或者子线程,父线程和子线程之间的生命周期并无必然联系。

转载于:https://my.oschina.net/u/242676/blog/2870672

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值