`
素寒丶玩玩
  • 浏览: 19508 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

转载 经典多线程讲解

 
阅读更多
 

彻底明白Java的多线程

标签: javastringclassthread多线程
 936人阅读 评论(0) 收藏 举报

彻底明白Java的多线程-线程间的通信(1) 
作者:恒善喜 来源:不详 (2006-06-02 14:51:45)

 
 线程间的通信
1. 线程的几种状态
线程有四种状态,任何一个线程肯定处于这四种状态中的一种:
1) 产生(New):线程对象已经产生,但尚未被启动,所以无法执行。如通过new产生了一个线程对象后没对它调用start()函数之前。
2) 可执行(Runnable):每个支持多线程的系统都有一个排程器,排程器会从线程池中选择一个线程并启动它。当一个线程处于可执行状态时,表示它可能正处于线程池中等待排排程器启动它;也可能它已正在执行。如执行了一个线程对象的start()方法后,线程就处于可执行状态,但显而易见的是此时线程不一定正在执行中。
3) 死亡(Dead):当一个线程正常结束,它便处于死亡状态。如一个线程的run()函数执行完毕后线程就进入死亡状态。
4) 停滞(Blocked):当一个线程处于停滞状态时,系统排程器就会忽略它,不对它进行排程。当处于停滞状态的线程重新回到可执行状态时,它有可能重新执行。如通过对一个线程调用wait()函数后,线程就进入停滞状态,只有当两次对该线程调用notify或notifyAll后它才能两次回到可执行状态。
2. class Thread下的常用函数函数
2.1 suspend()、resume()
1) 通过suspend()函数,可使线程进入停滞状态。通过suspend()使线程进入停滞状态后,除非收到resume()消息,否则该线程不会变回可执行状态。
2) 当调用suspend()函数后,线程不会释放它的“锁标志”。
例11:
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
if(shareVar==0){
for(int i=0; i<5; i++){
shareVar++;
if(shareVar==5){
this.suspend(); //(1)
}
}
}
else{
System.out.print(Thread.currentThread().getName());
System.out.println(" shareVar = " + shareVar);
this.resume(); //(2)
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start(); //(5)
//t1.start(); //(3)
t2.start(); //(4)
}
}
运行结果为:
t2 shareVar = 5
i. 当代码(5)的t1所产生的线程运行到代码(1)处时,该线程进入停滞状态。然后排程器从线程池中唤起代码(4)的t2所产生的线程,此时shareVar值不为0,所以执行else中的语句。
ii. 也许你会问,那执行代码(2)后为什么不会使t1进入可执行状态呢?正如前面所说,t1和t2是两个不同对象的线程,而代码(1)和(2)都只对当前对象进行操作,所以t1所产生的线程执行代码(1)的结果是对象t1的当前线程进入停滞状态;而t2所产生的线程执行代码(2)的结果是把对象t2中的所有处于停滞状态的线程调回到可执行状态。
iii. 那现在把代码(4)注释掉,并去掉代码(3)的注释,是不是就能使t1重新回到可执行状态呢?运行结果是什么也不输出。为什么会这样呢?也许你会认为,当代码(5)所产生的线程执行到代码(1)时,它进入停滞状态;而代码(3)所产生的线程和代码(5)所产生的线程是属于同一个对象的,那么就当代码(3)所产生的线程执行到代码(2)时,就可使代码(5)所产生的线程执行回到可执行状态。但是要清楚,suspend()函数只是让当前线程进入停滞状态,但并不释放当前线程所获得的“锁标志”。所以当代码(5)所产生的线程进入停滞状态时,代码(3)所产生的线程仍不能启动,因为当前对象的“锁标志”仍被代码(5)所产生的线程占有。
2.2 sleep()
1) sleep ()函数有一个参数,通过参数可使线程在指定的时间内进入停滞状态,当指定的时间过后,线程则自动进入可执行状态。
2) 当调用sleep ()函数后,线程不会释放它的“锁标志”。
例12:
class TestThreadMethod extends Thread{
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
for(int i=0; i<3; i++){
System.out.print(Thread.currentThread().getName());
System.out.println(" : " + i);
try{
Thread.sleep(100); //(4)
}
catch(InterruptedException e){
System.out.println("Interrupted");
}
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start(); (1)
t1.start(); (2)
//t2.start(); (3)
}
}
运行结果为:
t1 : 0
t1 : 1
t1 : 2
t1 : 0
t1 : 1
t1 : 2
由结果可证明,虽然在run()中执行了sleep(),但是它不会释放对象的“锁标志”,所以除非代码(1)的线程执行完run()函数并释放对象的“锁标志”,否则代码(2)的线程永远不会执行。
如果把代码(2)注释掉,并去掉代码(3)的注释,结果将变为:
t1 : 0
t2 : 0
t1 : 1
t2 : 1
t1 : 2
t2 : 2
由于t1和t2是两个对象的线程,所以当线程t1通过sleep()进入停滞时,排程器会从线程池中调用其它的可执行线程,从而t2线程被启动。
例13:
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
for(int i=0; i<5; i++){
System.out.print(Thread.currentThread().getName());
System.out.println(" : " + i);
try{
if(Thread.currentThread().getName().equals("t1"))
Thread.sleep(200);
else
Thread.sleep(100);
}
catch(InterruptedException e){
System.out.println("Interrupted");
}
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start();
//t1.start();
t2.start();
}
}
运行结果为:
t1 : 0
t2 : 0
t2 : 1
t1 : 1
t2 : 2
t2 : 3
t1 : 2
t2 : 4
t1 : 3
t1 : 4
由于线程t1调用了sleep(200),而线程t2调用了sleep(100),所以线程t2处于停滞状态的时间是线程t1的一半,从从结果反映出来的就是线程t2打印两倍次线程t1才打印一次。
2.3 yield()
1) 通过yield ()函数,可使线程进入可执行状态,排程器从可执行状态的线程中重新进行排程。所以调用了yield()的函数也有可能马上被执行。
2) 当调用yield ()函数后,线程不会释放它的“锁标志”。
例14:
class TestThreadMethod extends Thread{
public static int shareVar = 0;
public TestThreadMethod(String name){
super(name);
}
public synchronized void run(){
for(int i=0; i<4; i++){
System.out.print(Thread.currentThread().getName());
System.out.println(" : " + i);
Thread.yield();
}
}
}
public class TestThread{
public static void main(String[] args){
TestThreadMethod t1 = new TestThreadMethod("t1");
TestThreadMethod t2 = new TestThreadMethod("t2");
t1.start();
t1.start(); //(1)
//t2.start(); (2)
}
}
运行结果为:
t1 : 0
t1 : 1
t1 : 2
t1 : 3
t1 : 0
t1 : 1
t1 : 2
t1 : 3
从结果可知调用yield()时并不会释放对象的“锁标志”。
如果把代码(1)注释掉,并去掉代码(2)的注释,结果为:
t1 : 0
t1 : 1
t2 : 0
t1 : 2
t2 : 1
t1 : 3
t2 : 2
t2 : 3
从结果可知,虽然t1线程调用了yield(),但它马上又被执行了。 
 
 

(http://www.fanqiang.com

分享到:
评论

相关推荐

    从事计算机的人必读(不仅对只是还是对人生都大大有益,过来的高手所写,我只是转载)

    这本书以清晰易懂的方式讲解了Windows编程的基础知识,包括窗口、消息处理、图形绘制、多媒体支持、多线程编程以及Internet应用等方面。Petzold的讲解深入浅出,通过实例演示使读者能够快速上手实践。尽管书中的内容...

    转载牛人文章学习

    3. 详细讲解了Android中的Handler机制,包括其在多线程环境中的作用,以及如何有效地管理和使用Handler来管理UI更新和后台任务。 通过阅读这篇文章和相关文档,开发者可以增进对Android底层运作的理解,提升工具...

    Borland_C++Builder_6程序设计经典

    最后,书中可能还包括错误处理、性能优化、多线程编程、内存管理等方面的知识,这些都是C++Builder 6开发者必须掌握的基础技能。 附带的文件“Borland C++Builder 6程序设计经典[By_艳文].txt”可能是书籍的电子版...

    主要是Java技术栈的文章.zip

    提供在线阅读方式个人自建博客,CSDN博客。转载须知转载请联系GitHub出处,让我们共同...1、Java并发体系-第一阶段-多线程基础知识2、Java并发体系-第二阶段-锁与同步-[1]3、Java并发体系-第二阶段-锁与同步-[2]4、Jav

    ffmpeg资源转载

    6. **调试和性能优化**:文档可能还涵盖了如何使用 FFmpeg 的调试工具,以及如何通过优化代码来提升性能,例如多线程解码、硬件加速等。 7. **FFmpeg 的扩展与定制**:如果你有兴趣为 FFmpeg 贡献代码或者开发基于 ...

    Java工程师新人入门书籍推荐

    - 《深入理解Java虚拟机:JVM高级特性与最佳实践》:周志明的书,深入讲解JVM内存模型和多线程,对并发编程有较大帮助。 - 《Java EE 6 权威指南.基础篇.Basic concepts》:尽管现代开发更多依赖Spring等框架,...

    Qt教程及软件(超级浅显易懂,非常适合初学者)

    它还支持数据库、网络通信、多线程编程等功能,为开发者提供了全面的解决方案。 在教程中提到的Qt Creator是Qt官方提供的集成开发环境(IDE),它集成了源代码编辑器、编译器、调试器等工具,旨在提高Qt开发者的...

    MINA文档

    例如,单线程模型适合简单应用,而多线程模型可以处理高并发情况。 从压缩包文件的名称可以看出,其中包含的内容涵盖了MINA的快速开发、参考手册、使用手记和线程模型配置等多个方面: - **基于MINA框架快速开发...

    高效前端:Web高效编程与优化实践_机械工业出版社; 第1版 (2018年1月1日) 完整版-未加密

    0.2不等于0.3 203Effective前端20:明白WebAssembly与程序编译 209Effective前端21:理解JS与多线程 221Effective前端22:学会JS与面向对象 231Effective前端23:了解SQL 248Effective前端24:学习常用的前端算法与...

    Mastering C++ Game Development 无水印原版PDF

    6. 性能优化:讲解如何优化C++编写的代码以提升游戏性能,例如使用多线程、内存管理、渲染优化等技术。 7. 跨平台开发:介绍如何利用C++进行跨平台游戏开发,确保游戏能在不同的操作系统和设备上运行。 根据描述,...

    Beginning iPhone Development with Swift 4, 4th Edition

    书中内容涵盖了创建新项目、理解视图控制器、界面布局、事件处理、动画、多线程等iOS应用开发的核心知识点。同时,还会有对更高级主题的介绍,例如Swift语言中闭包和协议的用法,以及如何使用Core Data进行数据持久...

    Qt教程及软件(超级浅显易懂,非常适合初学者)

    Qt为开发者提供了创建图形用户界面应用程序的工具,并且能够处理文件、网络、多线程等底层操作。Qt支持C++和Python等编程语言,具有丰富的类库和API,因此被广泛应用于桌面、嵌入式和移动平台的软件开发。 该文档是...

    OGRE中文教程

    1. **效率特性**:OGRE优化了渲染流程,支持多线程,能有效地利用现代硬件资源。 2. **平台和3D API支持**:支持Windows、Linux、Mac OS X等操作系统,兼容Direct3D和OpenGL等多种3D图形接口,确保跨平台兼容性。 3....

    Learning Node.js Development

    - **单线程模型**:Node.js采用单线程模型来处理请求,这与传统的多线程模型不同,能够有效提高资源利用率。 - **模块化设计**:Node.js提供了一套丰富的内置模块,如fs(文件系统)、http(HTTP服务)等,方便...

    PINTOS PROJECT2 自己讲课用的PPT

    这包括了进程的生命周期管理,如创建、唤醒、睡眠和终止,以及多线程环境下的同步原语,如互斥锁、信号量和条件变量。 其次,内存管理是操作系统的重要组成部分。在PINTOS中,学生可能需要设计和实现虚拟内存系统,...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part2

    11.1 多线程的servlet模型 350 11.2 线程安全的servlet 351 11.2.1 变量的线程安全 351 11.2.2 属性的线程安全 360 11.3 singlethreadmodel接口 362 11.4 小结 363 11.5 思考题 363 第3部分 jsp篇 第12章 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part5

    11.1 多线程的servlet模型 350 11.2 线程安全的servlet 351 11.2.1 变量的线程安全 351 11.2.2 属性的线程安全 360 11.3 singlethreadmodel接口 362 11.4 小结 363 11.5 思考题 363 第3部分 jsp篇 第12章 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part4

    11.1 多线程的servlet模型 350 11.2 线程安全的servlet 351 11.2.1 变量的线程安全 351 11.2.2 属性的线程安全 360 11.3 singlethreadmodel接口 362 11.4 小结 363 11.5 思考题 363 第3部分 jsp篇 第12章 ...

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    11.1 多线程的servlet模型 350 11.2 线程安全的servlet 351 11.2.1 变量的线程安全 351 11.2.2 属性的线程安全 360 11.3 singlethreadmodel接口 362 11.4 小结 363 11.5 思考题 363 第3部分 jsp篇 第12章 ...

Global site tag (gtag.js) - Google Analytics