`
leogao_emcom
  • 浏览: 82491 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

有关Java 5.0+ 并发包的探讨-1 section

阅读更多

基础结构:
在Java的Thread体系中,最基础的就是Runnable接口,它代表了一个线程功能的“契约”,或者是线程的功能在Java中的表述,因为线程不是哪个语言的特有,而是操作系统的特有,所以这里就给予一个中性的描述“此接口就是一个线程功能在Java中的表述”,请看它在Java中声明的结构:

  public interface java.lang.Runnable {
  public void run();
  }


这类似Command设计模式,只提供一个方法抽象,代表所有的“命令”,这里也有这样的意思,也就是用这个接口就可以描述一个线程“想干什么”的问题,我们可以实现这个接口:

 
public class dosomethingThread implements Runnable {

	@Override
	public void run() {
		System.out.println("do somethings");
		
	}

}


这是一个正常的方式,还可以使用下面这样方式:

  public class ThreadBasicDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Runnable runnableInterface = new Runnable() {

			@Override
			public void run() {
				System.out.println("do somethings");

			}

		};

	}

}


有了想让线程做什么事情的“核”,接下来就应该把这个“核”包裹在一个真正的线程中了,在Java中,线程是用Thread类表示的,这个类包装了与操作系统交互而管理线程的逻辑,我们不用知道!不过喜欢探索的家伙可能还是喜欢看一看咋回事!所以我这里列出一个Thread的Start方法在JDK实现片段(一个线程是Start方法启动的):

  public synchronized void start() {
        /**
	 * This method is not invoked for the main method thread or "system"
	 * group threads created/set up by the VM. Any new functionality added 
	 * to this method in the future may have to also be added to the VM.
	 *
	 * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0 || this != me)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
	    stop0(throwableFromStop);
	}
    }

    private native void start0();

 可以看到其注释中说明是JVM来创建线程的,而不同OS的JVM实现是具体与OS打交道的,那个native void start0()方法,没有实现体,是JVM实现的,就像是C#调用windows API一样,不过这里是调用JVM的"API".所以你必须知道创建线程和管理线程这事情是由JVM通信OS来实现的,是OS所特有的东西,和具体语言无关!当然也和平台无关,如.Net,Java,Python等等.

另外这个类直接从Runnable接口实现而来,所以这里需要澄清的是,它只是实现了run方法为一个空壳,里面没有具体功能,看一下它的构造函数:

可以看到具体干活的还是Runnable的实例,只是注入到Thread中而已,那么为什么Thread从Runnable实现,这就像一个适配器,一个默认的实现,我们可以直接重载Thread的run方法做一些事情(功能),而不必再用注入的方式使用它,而且从语义来讲,“功能的核”和“线程的壳“是在一起的,那么就会产生干不同活的Thread:

Java内建了很多具备不同功能的Thread类型(不仅有功能还是线程!)。
对于我们自己的功能线程,是使用继承覆盖还是接口注入的方式,完全取决于你。

 public class ThreadBasicDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Runnable runnableInterface = new Runnable() {

			@Override
			public void run() {
				System.out.println("do somethings");

			}

		};
		Thread newThread=new Thread(runnableInterface);
		newThread.start();

	}

}


使一个线程在操作系统中创建出来,只需要调用Thread的start方法即可,它知道如何在操作系统中创建线程,确切的说是在当前进程中创建,另外这里还提供了一个抽象层,那就是不管你是什么操作系统(windows,unix,linux),不管这些OS创建线程的方式有什么不同,它都能自动处理,调用方不需要知道!。另外Executor也可以执行一个Runnable所代表的任务,后面的文章中会有讲。

上面是创建线程的两种方式,都在java.lang包中,另外你可能注意到在run方法中只是返回一个void,也就是说不支持返回某些结果,但是很多时候你希望返回一些结果,幸好Java 5.0提供了Callable接口(在java.util.concurrent包中),它的作用和Runnable接口一样,但是它允许返回结果,在Java中它被声明成:

public interface java.util.concurrent.Callable {
  public java.lang.Object call() throws java.lang.Exception;
}


可以看到它与Runnable不同的地方就是可以返回结果(任何类型的),还可以抛出异常!
在使用方面,它不能与Thread联合直接使用,比如在构造函数中注入使用,因为如果等待一个结果的返回,就等于让主程序堵塞,所以它需要和Future一起配合使用,Future也是一个并发包中新类,代表了未来要”取“的结果:

  Callable<Object> callableInterface=new Callable<Object>() {

			@Override
			public Object call() throws Exception {
				System.out.println("do somethings");
				return null;
			}
		};


此接口还使用了泛型,也就是说我们可以为其设定任何返回类型。

ExecutorService threadpool = Executors.newFixedThreadPool(2);
Future<Object> p = threadpool.submit(callableInterface);


之后就可以通过Future的get方法取得结果,get会等待最终得到的结果,可以看出这是一个异步模型,也就是说”提交“给ExecutorService之后,就可以放任不管了,不会使主程序堵塞。对于ExecutorService,我会在后面的文章中讲到。

状态控制:
所有的线程都有生命周期,其中要经历的状态有(可以通过getState方法来查询):

NEW
Thread已被创建,但其start() method尚未被调用。所有线程都会从这个状
开始

RUNNABLE
线程正在运行或在操作系统调度它时就可运行。
BLOCKED
因为线程在等待取得锁定以便进入同步方法或程序块,所以线程并未运行。
WAITING
线程因为调用了 Object.wait()或Thread.join()而未运行。
TIMED_WAITING
线程因为调用了 Thread.sleep()或加上逾时值来调用 Object.wait()
Thread.join()而未运行。
TERMINATED
线程已运行完毕。它的 run()已正常结束或通过抛出异常而结束。

你可能很奇怪,Object.wait是干什么的,这是Java在所有类型基类Object中封装的方法,也就是说不管你是什么类型都有这个方法,不光只有这一个方法,还有notify和notifyAll方法,干什么用的哪?
wait就是把当前对象所在线程设置到等待状态,直到另外一个线程调用那个线程的Notify或者notifyAll来”通知“前面提到的那个线程结束等待状态继续运行,这对于一个等着另一个的场景实现很有帮助,另外后面的文章还会介绍一个semaphore类似于信号量的东西,也可以更加简单的做这样的事情。

异常处理
当一个线程出现了异常时,线程进入终止状态,但是如何处理这个异常哪?

 newThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
			
			@Override
			public void uncaughtException(Thread arg0, Throwable arg1) {
				//do somethings
				
			}
		});



线程的优先级
线程可以以不同的优先级运行。 指定优先级的线程通常会在已无具较高优先级的线程等
待时才会运行。在运作线程优先级时,你可以使用这里的一些程序代码:

// 将线程优先级设定为低于一般标准
t.setPriority(Thread.NORM_PRIORITY-1);
// 将线程的优先级设定为低于当前线程
t.setPriority(Thread.currentThread().getPriority() - 1);
// 不需等待I/O的线程应该要明确地让出CPU,以让其他具有相同优先
// 级的线程有机会运行
Thread t = new Thread(new Runnable() {
  public void run() {
    for(int i = 0; i < data.length; i++) { // 逐一处理一组数据
      process(data[i]); // 加以处理
      if ((i % 10) == 0) // 但在每处理10个后,就暂
        Thread.yield(); // 停以让其他线程运行
    }
  }
});


其中线程的yield方法起到一个复合作用,不像wait只是挂起当前线程,而是挂起当前线程,并通知其他线程开始运行。

Thread类的其他方法说明
stop():停止当前线程
sleep(..):让当前线程休眠一段时间
Thread.currentThread():得到当前线程
........
都比较简单,这里就不再描述和讲解了。下一篇将讲解线程的调度(全在java.util.concurrent包中,越来越进入到核心部分了)。


 

0
1
分享到:
评论
3 楼 leogao_emcom 2010-11-07  
有优先级倒置的情况,这就不符合线程原先制定的优先级了:
如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。
另外是不是不同的操作系统会造成差异,还没有核实。需要继续调研,
2 楼 liangguanhui 2010-11-03  
francis.xjl 写道
线程的优先级好像不一定管用

貌似是需要操作系统支持的说。
1 楼 francis.xjl 2010-11-03  
线程的优先级好像不一定管用

相关推荐

    Vue 3.0+Vite 2.0+Vue-Router4.0+Element-Plus+Echarts 5.0后台管理系统

    Vue 3.0+Vite 2.0+Vue-Router4.0+Element-Plus+Echarts 5.0+Axios 开发的后台管理系统 Vue 3.0+Vite 2.0+Vue-Router4.0+Element-Plus+Echarts 5.0+Axios 开发的后台管理系统 Vue 3.0+Vite 2.0+Vue-Router4.0+...

    dotnet-sdk-5.0.202-win-x64.exe

    dotnet-sdk-5.0.202-win-x64.exe

    dotnet-sdk-5.0.400-linux-x64.tar.gz

    本文将详细介绍dotnet-sdk-5.0.400-linux-x64及其包含的组件,探讨其在跨平台开发中的重要性。 首先,"dotnet-sdk-5.0.400-linux-x64.tar.gz"是一个针对Linux x64架构的.NET SDK压缩包。这个版本5.0.400代表了.NET ...

    SSH整合jar包-spring5.0+hibernate5.1+struts2.5

    SSH整合是指将Spring、Hibernate和Struts这三大Java开源框架集成在一起,用于构建高效、灵活的企业级Web应用程序。这三个框架分别负责不同的职责:Spring作为应用的基石,提供依赖注入(DI)和面向切面编程(AOP),...

    Apache2.2.4+php5.2.5+mysql5.0+discuz!6+ ZendOptimizer-3.3.0a+phpMyAdmin-2.11.3

    这个是安装说明文件,里面要用的安装文件,除了MYSQL 5。0太大,不能上传,其他的都上传了!!安装文件免费共享了,想快速安装成功的兄弟,请下载这个说明文件,我要收3分哦!我也想去下别人的好东西!...

    电脑软件CGI-Plus-v5.0.0.5-x86-x64.rar

    电脑软件CGI-Plus_v5.0.0.5_x86-x64

    phoenix-5.0.0.3.1.4.0-315.tar.gz

    ambari-2.7.5 编译过程中四个大包下载很慢,所以需要提前下载,包含:hbase-2.0.2.3.1.4.0-315-bin.tar.gz ,hadoop-3.1.1.3.1.4.0-315.tar.gz , grafana-6.4.2.linux-amd64.tar.gz ,phoenix-5.0.0.3.1.4.0-315....

    thinkphp5.0+phpmailer-demo

    1. **ThinkPHP5.0框架**:ThinkPHP5.0是基于PHP语言的一个轻量级、快速、强大的开发框架,它遵循MVC(模型-视图-控制器)设计模式,提供了丰富的功能和良好的扩展性。在该项目中,ThinkPHP5.0将作为后台处理逻辑的...

    CentOS-5.0-i386-bin-DVD.part04.rar

    CentOS-5.0-i386-bin-DVD.part04.rar

    CentOS-5.0-i386-bin-DVD.part06.rar

    CentOS-5.0-i386-bin-DVD.part06.rar

    Understand-5.0.930-Windows-64bit.exe

    Understand-5.0.930-Windows-64bit.exe windows Understand-5.0.930-Windows-64bit.exe

    winrar 5.0 + key

    winrar 5.0 + key

    gradle-5.0-milestone-1-all.zip

    在本文中,我们将深入探讨Gradle 5.0 Milestone 1的主要特性和改进,以及它如何影响开发者的工作流程。 1. **性能提升** - **更快的初始化**:Gradle 5.0引入了更快的项目初始化速度,通过缓存项目元数据来减少...

    达内JAVA TTS5.0 PDF----ORACLE编程

    【标题】"达内JAVA TTS5.0 PDF"涵盖了Oracle编程的相关知识,这通常意味着这份资料是关于Java编程与Oracle数据库的结合使用。Oracle编程主要指的是如何利用Java语言进行Oracle数据库的交互,包括数据的增删查改、...

    NCB-PCI_Express_Base_5.0r1.0-2019-05-22.pdf

    在协议层,PCIe 5.0继续采用TLP(事务层包)和DLLP(数据链接层包)的设计,但对这些包的处理进行了优化,以减少延迟并提高带宽利用率。同时,它还增强了对流控制、错误处理和多路复用的支持。 总的来说,"NCB-PCI_...

    llvm5.0-libs-5.0.1-7.el7.x86-64.rpm

    llvm5.0-libs-5.0.1-7.el7.x86-64.rpm

    达内JAVA TTS5.0 PDF----JAVA SE核心1

    《达内JAVA TTS5.0 PDF——JAVA SE核心1》是针对初学者和有一定基础的Java开发者设计的一份详尽教程,旨在深入探讨Java Standard Edition(Java SE)的核心概念和技术。这份PDF教程出自达内教育,一家知名的IT培训...

    RP2040开发板自制树莓派逻辑分析仪LogicAnalyzer-5.0.0.0上位机软件

    RP2040开发板自制树莓派逻辑分析仪LogicAnalyzer-5.0.0.0上位机软件 包含: LogicAnalyzer-5.0.0.0-linux-arm.zip LogicAnalyzer-5.0.0.0-linux-arm64.zip LogicAnalyzer-5.0.0.0-linux-x64.zip LogicAnalyzer-5.0....

    JDK1.6.0_07+Tomcat5.0+Myeclipse-8.5.0

    JDK1.6.0_07+Tomcat5.0+Myeclipse-8.5.0-搭建开发环境 在软件开发和项目实施中,搭建一个完整的开发环境是一个非常重要的步骤。这个环境包括了JDK、Tomcat和Myeclipse三个主要组件。下面我们将详细介绍如何搭建这个...

    thinkphp5.0+PHPExcel-demo

    通过研究和实践这个demo,开发者可以掌握在ThinkPHP5.0中利用PHPExcel进行Excel操作的基本技巧,并为自己的项目带来更丰富的功能。同时,这也是一次了解和熟悉这两种工具的好机会,对于提升PHP Web开发技能大有裨益...

Global site tag (gtag.js) - Google Analytics