惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - frank.net

中国软件工业的冤枉路 随便写写 windows2000实现双机热备份(转) 规范软件开发过程-软件配置管理实践 多线程编程 高级主题(二)注:转 多线程编程 高级主题(一)注:转 多线程编程 秘籍篇(二)注:转 多线程编程 秘籍篇(一)注:转 多线程编程 实践篇(五)注:转 - frank.net - 博客园 多线程编程 实践篇(四)注:转 - frank.net - 博客园 多线程编程 实践篇(二)注:转 多线程编程 实践篇(一)注:转 多线程编程 基础篇(四)注:转 多线程编程 基础篇(三)注:转 多线程编程 基础篇(二)注:转 多线程编程 基础篇(一)注:转 多线程编程 关于创业方向和项目 Servlet Cookie操作总结
多线程编程 实践篇(三)注:转
frank.net · 2008-10-07 · via 博客园 - frank.net

[深入了解线程对象与线程,线程与运行环境]

在基础篇中的第一节,我就强调过,要了解多线程编程,首要的两个概念就是线程对象
和线程.

现在我们来深入理解线程对象,线程,运行环境之间的关系,弄清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对象.这样,我们就有了:

    [一个对象的多个线程]
    这是以后我们要介绍的线程池的重要概念.