多线程编程 实战篇 (三)
2015-08-12 21:49
232 查看
[深入了解线程对象与线程,线程与运行环境]
在基础篇中的第一节,我就强调过,要了解多线程编程,首要的两个概念就是线程对象
和线程.
现在我们来深入理解线程对象,线程,运行环境之间的关系,弄清Runnable与Thread的
作用.
序列化机制,你就不能称得一个java程序员.
的对象,这种对象说到底就是内存中一些数据的组合.只要按一定位置和顺序组合就能
完整反映这个对象.
被序列,否则在另外的环境和时序中就无法”还原”.
端口之间建立的一个物理连结,如果它被序列化,那么在另一个时刻在另一个主机上它如
何能被还原?Socket连结一旦断开,就已经不存在,它不可能在另一个时间被另一个主机
所重现.重现的已经不是原来那个sc对象了.
个线程对象所在有主机的运行环境相关的信息,线程调度机制,安全机制等只特定于当前
运行环境的信息,假如它被序列化,在另一个环境中运行的时候原来初始化的运行环境的
信息就不可能在新的环境中运行.而假如要重新初始化,那它已经不是原来那个线程对象
了.
要想传送数据,你还要getInputStream和getOutputStream,并read和write,两台主机之间
才开始真正的”数据连结”
只有当它调用start()后,当前环境才会分配给它一个运行的”空间”,让这段代码开始运行.
这个运行的”空间”,才叫真正的”线程”.也就是说,真正的线程是指当前正在执行的那一个
“事件”.是那个线程对象所在的运行环境.
束实现者强制提供匹配的方法,并将实现该接口的类的实例作为参数来提供给调用者,这是
JAVA平台实现回调的重要手段.
实现的操作中的算法和数据封装到一个run方法中(由于算法本身是数据的一个部分,所以我
把它们合并称为数据),可以将离数据和环境的逻辑分离开来.使程序员只关心如何实现我
想做的操作,而不要关心它所在的环境.当真正的需要运行的时候再将这段”操作”传给一个
具体当前环境的Thread对象.
同时访问.简单说:
也就是”一个数据实例对应多个线程”.
到Runnable的run()方法中,把Runnable实例从外部传给多个Thread对象.这样,我们就有了:
原文作者:axman
原文出处:http://blog.csdn.net/axman/article/details/443431
个人觉得此博主写得文章非常好,推荐大家翻阅。
在基础篇中的第一节,我就强调过,要了解多线程编程,首要的两个概念就是线程对象
和线程.
现在我们来深入理解线程对象,线程,运行环境之间的关系,弄清Runnable与Thread的
作用.
在JAVA平台中,序列化机制是一个非常重要的机制,如果不能理解并熟练应用
序列化机制,你就不能称得一个java程序员.
在JAVA平台中,为什么有些对象中可序列化的,而有些对象就不能序列化? 能序列化的对象,简单说是一种可以复制(意味着可以按一定机制进行重构它)
的对象,这种对象说到底就是内存中一些数据的组合.只要按一定位置和顺序组合就能
完整反映这个对象.
而有些对象,是和当前环境相关的,它反映了当前运行的环境和时序,所以不能
被序列,否则在另外的环境和时序中就无法”还原”.
比如,一个Socket对象: Socket sc = new Socket("111.111.111.111",80); 这个sc对象表示当前正在运行这段代码的主机和IP为"111.111.111.111"的80
端口之间建立的一个物理连结,如果它被序列化,那么在另一个时刻在另一个主机上它如
何能被还原?Socket连结一旦断开,就已经不存在,它不可能在另一个时间被另一个主机
所重现.重现的已经不是原来那个sc对象了.
线程对象也是这种不可序列化对象,当我们new Thread时,已经初始化了当前这
个线程对象所在有主机的运行环境相关的信息,线程调度机制,安全机制等只特定于当前
运行环境的信息,假如它被序列化,在另一个环境中运行的时候原来初始化的运行环境的
信息就不可能在新的环境中运行.而假如要重新初始化,那它已经不是原来那个线程对象
了.
正如Socket封装了两个主机之间的连结,但它们并不是已经连结关传送数据了.
要想传送数据,你还要getInputStream和getOutputStream,并read和write,两台主机之间
才开始真正的”数据连结”
一个Thread对象并建立后,只是有了可以"运行"的令牌,仅仅只是一个"线程对象".
只有当它调用start()后,当前环境才会分配给它一个运行的”空间”,让这段代码开始运行.
这个运行的”空间”,才叫真正的”线程”.也就是说,真正的线程是指当前正在执行的那一个
“事件”.是那个线程对象所在的运行环境.
明白了上面的概念,我们再来看看JAVA中为什么要有Runnable对象和Thread对象. 一.从设计技巧上说,JAVA中为了实现回调,无法调用方法指针,那么利用接口来约
束实现者强制提供匹配的方法,并将实现该接口的类的实例作为参数来提供给调用者,这是
JAVA平台实现回调的重要手段.
二.但是从实际的操作来看,对于算法和数据,是不依赖于任何环境的.所以把想要
实现的操作中的算法和数据封装到一个run方法中(由于算法本身是数据的一个部分,所以我
把它们合并称为数据),可以将离数据和环境的逻辑分离开来.使程序员只关心如何实现我
想做的操作,而不要关心它所在的环境.当真正的需要运行的时候再将这段”操作”传给一个
具体当前环境的Thread对象.
三.这是最最重要的原因,[实现数据共享] 因为一个线程对象不对多次运行.所以把数据放在Thread对象中,不会被多个线程
同时访问.简单说:
class T extends Thread{ Object x; public void run(){//......;} } T t = new T(); 当T的实例t运行后,t所包含的数据x只能被一个t.start();对象共享,除非声明成 static Object x; 一个t的实例数据只能被一个线程访问.意思是"一个数据实例对应一个线程". 而假如我们从外部传入数据,比如 class T extends Thread{ private Object x; public T(Object x){ this.x = x; } public void run(){//......;} } 这样我们就可以先生成一个x对象传给多个Thread对象,多个线程共同操作一个数据.
也就是”一个数据实例对应多个线程”.
现在我们把数据更好地组织一下,把要操作的数据Object x和要进行的操作一个封装
到Runnable的run()方法中,把Runnable实例从外部传给多个Thread对象.这样,我们就有了:
[一个对象的多个线程] 这是以后我们要介绍的线程池的重要概念.
原文作者:axman
原文出处:http://blog.csdn.net/axman/article/details/443431
个人觉得此博主写得文章非常好,推荐大家翻阅。
相关文章推荐
- jdk版本的特点
- Lua笔记11-迭代器和闭包
- php入门实现留言板
- Java学习之路0812(doGet和doPost)
- ios学习之旅---c语言函数
- Java学习之路0811(预编译、事务、web项目)
- Delphi FastReport动态加载图片 (转载)
- c++函数指针与默认参数
- 【Struts2学习笔记-4】包含其他配置文件
- 量化分析师的Python日记【第1天:谁来给我讲讲Python?】
- Eclipse 调试jar包源码
- 编写高质量代码改善C#程序的157个建议——建议11: 区别对待==和Equals
- leetcode-Spiral Matrix II 螺旋矩阵2之python大法好,四行就搞定,你敢信?
- 如何判断机器的字节顺序是高字节在前还是低字节在前
- 开发web应用之php
- python离线安装setuptools
- 从错误中学python(3)——求素数
- JAVA 访问 SOAP 协议
- c++, class的大小
- C语言小知识(待续)