`
素寒丶玩玩
  • 浏览: 19677 次
  • 性别: 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

分享到:
评论

相关推荐

    转载牛人文章学习

    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框架快速开发...

    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,因此被广泛应用于桌面、嵌入式和移动平台的软件开发。 该文档是...

    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章 ...

    mina

    4. **Apache MINA 线程模型配置 .shtml**:这部分内容可能专注于MINA的线程模型,MINA支持多种线程模型,如NIO多路复用器、简单的线程池等,以优化性能和并发处理能力。 5. **NIO_TEST**:这可能是一些与Java NIO...

Global site tag (gtag.js) - Google Analytics