`
当代阿Q
  • 浏览: 62863 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

并发编程 二 之 线程驱动任务

阅读更多
前序:
     我们前面说了,我们的程序是可以分成若干个程序片段的,而每一个程序片段我们都可以用来做为一在多个任务;当然做为独立可运行的任务将更为理想化;在多线程来实现并发的手段时,我们常常将没一个任务用一个独立的线程来进行驱动;
   
      下面是一个简单的线程来驱动我们的一个任务的执行;
1.任务的描述
/**
 * 一个简单的任务类
 * @author liuwei 继承于Runnable接口,并提供Run方法的实现
 * Runnable为描述任务的方式
 */
public class SimpleTask implements Runnable {
	/**
	 * 任务执行总数
	 */
	protected int countDown = 10;

	private static int taskCount = 0;

	/**
	 * 任务执行次数id
	 */
	private final int id = taskCount++;

	/**
	 * 无参构造函数
	 */
	public SimpleTask() {
	}
	/**
	 * 带参构造函数
	 * @param countDown
	 */
	public SimpleTask(int countDown) {
		this.countDown = countDown;
	}
	/**
	 * 显示任务的信息
	 * @return
	 */
	public String status() {
         return "#" + id + "(" + (countDown > 0? String.valueOf 
         (countDown):"SimpleTask!")+ "), ";
	}

	/**
	 * 任务的执行方法
	 */
	public void run() {
	while (countDown-- > 0) {
	   System.out.print(status());
	   /**
	    * 对线程调度器的一种建议,即java线程机制的一部分,
	     * 可以将cpu从一个线程转到另一个线程,且类似告诉
	     * 别人,我这里目前不需要占用现在的内存资源了;
	     * 我们可以说它是一个上下文切换的一个动作;
	     */
	   Thread.yield();
           }
	}
}


这个单独的任务,并不能够独立的执行;且也不具有产生任务内在的线程能力;而且,要实现线程行为,还必须显式的将这个任务附到线程上去;

2.线程的描述
   在java中,将Runnable对象转变成工作任务的传统方式就是将它将给线程,并由线程来驱动它执行;这一点和Quartz里的Job与Scheduler有点相似;即作业不能够自己运行,它需要在Scheduler上进行注册后,由任务调度器来负责管理它;
   下面我们来实现一个线程驱动任务的执行;
/**
 * 一个线程来驱动任务的执行
 * @author liuwei
 */
public class TreadDriverTask {
    
  /**
   * 当通过线程thread的start方法调用任务的run方法的时候,
    * main函数所对应的线程将继续执行System的语句;它不会等待
    * thread执行完毕后再执行System操作;
    * 我们前面说过,一个线程就是在进程中有一个单一的顺序控制流;
    * @param args
    */
   public static void main(String[] args){ 
       Thread thread=new Thread(new SimpleTask());
       thread.start();
       System.out.println("---->main执行的现成与线程thread是相互独立
        的!");
   }
}

它的执行情况为:
---->main执行的现成与线程thread是相互独立的!
#0(9), #0(8), #0(7), #0(6), #0(5), #0(4), #0(3), #0(2), #0(1), #0(SimpleTask!),

我们来看看多个现在执行多个任务的时候,它是一个什么样的情况!
/**
 * 多个线程来驱动任务的执行
 * @author liuwei
 */
public class MultThreadDriverTask {
    
  /**
   * 当通过线程thread的start方法调用任务的run方法的时候,
    * main函数所对应的线程将继续执行System的语句;它不会等待
    * thread执行完毕后再执行System操作;
    * 我们前面说过,一个线程就是在进程中有一个单一的顺序控制流;
    * @param args
    */
   public static void main(String[] args){ 
	for(int i=0;i<5;i++){
	new Thread(new SimpleTask()).start();
         }
     System.out.println("---->waiting for ......!");
   }
}

它的执行效果如下:
#0(9), #1(9), ---->waiting for ......!
#0(8), #3(9), #1(8), #3(8), #2(9), #1(7), #4(9), #0(7), #2(8), #4(8), #0(6), #2(7), #4(7), #0(5), #2(6), #4(6), #0(4), #2(5), #4(5), #0(3), #2(4), #4(4), #0(2), #2(3), #4(3), #0(1), #3(7), #2(2), #4(2), #1(6), #0(SimpleTask!), #3(6), #2(1), #1(5), #4(1), #3(5), #2(SimpleTask!), #1(4), #4(SimpleTask!), #3(4), #1(3), #3(3), #1(2), #3(2), #1(1), #3(1), #1(SimpleTask!), #3(SimpleTask!),
我们可以看出:
当通过for循环分别创建5个线程的时候,在创建的过程中是有一定的时间差的;比如我在创建第5个线程的时候,可能第一个创建的线程已经开始执行附属任务的run方法;且所有线程创建完毕后(这个是由main所在线程内完成的),则执行了System操作;而前面创建的5个线程,他们将自己运行自己的;
另一个特点是,他们的输出是相互混乱的;因为线程间的相互切换是由线程调度器来进行自动控制的;对于单处理器的环境,则调度器将将cpu时间片分给不同的线程进行占用;而对于多处理器的环境,则线程调度器将会在多个处理器之间默默的分发线程;

3.线程调度机制的非确定性
  对于上面的结果,可能每一次运行的输出也是不一样的;因为这就是线程调度机制的非确定性,同样,对于不同的jdk版本,其运行的输入也不一样;首先对于同一jdk版本下的运行结果的不一致,是因为对于每一次的运行,它的cpu时间片的分配可能进行不同的分配(单处理器环境),它的任务处理器也可能每次分配的线程也不一致(多处理器环境);对于不同jdk版本,在sun的早期jdk,cpu时间的切片动作不是很频繁,可能上面的5个线程,线程1执行完后,线程2才会执行;它启动所有线程的代价相对现有jdk的启动可能代价更高;现在的jdk,时间切片行为更为完善,每个线程看起来都会获得更加正规的服务(处理器服务于它);

4.main函数为何没有对启动的线程进行异常捕获且没有引用的Thread没有被垃圾回收
   在上面的main方法里创建Thread对象的时候,它并没有去捕获这些对象的引用;通常大家都知道,对于一个对象没有引用指向他,则它将被垃圾回收器定时回收;但对于thread就不同了,每个thread都注册了自己,因为确实有一个引用指向它,且只有当run方法执行完毕后,垃圾回收器才会清楚它;且我们说过了mian方法,与启动的每一个thread是相互独立的,我们不能够在A线程1去捕获B线程下可能存在的异常;
分享到:
评论

相关推荐

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │ 高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │ 高并发编程第一阶段37讲...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4 │ 高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4 │ 高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4 │ 高并发编程第一阶段37讲...

    Java虚拟机并发编程

    《java虚拟机并发编程》是java并发编程领域的里程碑之作,由资深java技术专家、并发编程专家、敏捷开发专家和jolt大奖得主撰写,amazon五星级畅销书。它系统深入地讲解在jvm平台上如何利用jdk同步模型、软件事务内存...

    完结13章一课掌握Java并发编程精髓

    Java并发编程从入门到进阶 多场景实战,众所周知,并发编程是优秀工程师的标准之一,但知识庞杂,复杂性高,常常让人望而却步。但如果没有掌握背后的核心原理,你开发的代码可能会成为难以调试和优化的头疼问题。在...

    并发编程-事件驱动模型1

    1、传统的编程模式 2、事件驱动模型 3、第三种就是协程、事件驱动的方式,一般普遍认为第(3)种方式是大多数网络服务器采用的方式 1、创建一个线程循环检测是否有

    Java多线程之进阶篇(一).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    Java多线程之基础篇(一).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    高并发事件驱动服务器研究

    本文对高并发服务器中使用事件驱动编程模型进行了分析和研究,提出了一种混合使用事件和多线程技术的 服务器软件体系结构,使用高级Pet ri 网对混合多线程阶段化事件驱动结构进行了建模,并与传统多线程模型进行了性能 ...

    Java多线程之进阶篇(二).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    Java多线程之基础篇(二).docx

    与此相反,像java所使用的这种并发系统会共享内存或I/O这样的资源,因此编程编写多线程程序最基本的困难在于,协调不同线程驱动的任务之间这些资源的使用,以便使得这些资源不会同时被多个任务访问。

    增加并发控制后的globalmem程序

    增加并发控制后的globalmem程序

    C++ 百万并发网络通信引擎架构与实现 (Socket、全栈、跨平台).rar

    C++网络编程技术: 学习使用C++语言进行网络编程的方法和技巧,包括Socket编程、多线程编程等。 高性能、高并发设计: 掌握设计和实现高性能、高并发的网络通信引擎的方法和技术,包括事件驱动、异步IO等。 全栈开发...

    Java高并发异步Socket编程

    DougLee可扩展的网络服务事件驱动Reactor模式基础版多线程版其他变体java.io包中分阻塞IOAPI一览Web服务器,分布式对象系统等等它们的共同特点Read请求解码请求报文业务处理编码响应报文发送响应实际应用中每一个...

    java乐器源码-concurrency:Java并发编程知识梳理以及常见处理模式featuresandpatterns

    并发编程解决的核心问题 分工(如何高效地拆解任务并分配给线程)Fork/Join 框架 同步(指的是线程之间如何协作)CountDownLatch 互斥(保证同一时刻只允许一个线程访问共享资源)可重入锁 如何学习 跳出来,看全景...

    网络编程教程,很好的一本写linux网络编程书,这是我上传的源码

     15.3.3 多进程的并发服务器和多线程的并发服务器  15.3.4 客户端进程的多线程化  本章小结 第十六章 网络售票系统的简单模拟  16.1 系统的总体设计  16.1.1 应用的说明  16.1.2 数据格式的...

    unix网络编程源码

    《unix网络编程》书中的源代码 ·TCP传输和UDP传输  ·套接口编程:基本、高级、路由、原始等 ·I/O:复用、非阻塞、信号驱动、... ·程序设计:TCP迭代服务器、并发服务器、预先派生子进程服务器、预先线程服务器等

    《精通Linux 设备驱动程序开发》.(Sreekrishnan).pdf

    13.3.2 alsa编程287 13.4 调试288 13.5 查看源代码289 第14章 块设备驱动程序291 14.1 存储技术291 14.2 linux块i/o层295 14.3 i/o调度器295 14.4 块驱动程序数据结构和方法296 14.5 设备实例:...

    linux programming instances网络编程教程 附源代码

    5.2 实例之二 5.2.1 服务器端代码-tcpserver.c 5.2.2 客户端代码-tcpclient.c 5.3 本章小结 第6章 udp数据报 6.1 udp通讯机制 6.1.1 基本通讯过程 6.1.2 udp与tcp的比较 6.1.3 连接的udp 6.1.4 udp...

    UNIX网络编程卷2进程间通信

    本书是一部UNIX网络API的经典之作!...I/O:复用高级函数,非阻塞和信号驱动 守护进程和inetd UNIX域协议 ioctl操作 广播和组播 线程 流 设计:TCP迭代的、并发的、预先创建的和预先线程化的服务器

    精通LINUX设备驱动程序开发

    271 第13章 音频驱动程序 273 13.1 音频架构 273 13.2 linux声音子系统 275 13.3 设备实例:mp3播放器 277 13.3.1 驱动程序函数和结构体 278 13.3.2 alsa编程 287 13.4 调试 288 13.5 查看源代码 289 第14章...

Global site tag (gtag.js) - Google Analytics