`
lc52520
  • 浏览: 369272 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

java线程的两个陷阱【Z】

    博客分类:
  • java
阅读更多

在使用java 线程的时候,特别是初学者总会有几点很常见的误区,下面以以下代码为例:

  线程类:

package threadtest1;
public class ReturnThreadInfo extends Thread {
    private String str;

    public ReturnThreadInfo() {
        this.str = "Hello";
    }
   
    public void run(){
        try{
            this.str = "Hello World!";
        }catch(Exception ex){
           
        }
    }
   
    /*返回线程信息:str变量的值*/
    public String getThreadInfo(){
        return this.str;
    }
}

  主类:

package threadtest1;
public class Main extends Thread {
   
    public Main() {
    }
   
    public static void main(String[] args) {
        ReturnThreadInfo returnThreadInfo = new ReturnThreadInfo();
        returnThreadInfo.start();
        System.out.println(returnThreadInfo.getThreadInfo());
    }
}

   大家可以看到这个程序主要功能是返回线程returnThreadInfo对象的变量str的值并输出,那么str的值到底是什么,一些人可能会认为 是"Hello world!"或是null,其实如果大家运行下就会知道输出的str的值实际是"Hello"。为什么呢?其实认为输出结果是"Hello world"或是null的人存在着两个比较常见的误区:

  1、误区一:认为returnThreadInfo对象中的run方法一定在主类的System.out.println(returnThreadInfo.getThreadInfo())之间运行。

   这是比较常见的一个误区,稍微了解一些java编译原理的人应该清楚,java源文件的代码编译是自上而下的,也就是处在同一文件上面的代码会在下面的 代码之间被编译和运行。所以很多人认为returnThreadInfo.start()先被运行,returnThreadInfo线程被启动,然后 run()方法被调用,str被赋值:"hello world!",然后线程结束并返回到主类,最后调用 System.out.println(returnThreadInfo.getThreadInfo())将str的值输出就是"Hello world!"。

  如果returnThreadInfo不是一个线程而是一个普通类的对象,那么输出的结果是"Hello world",但是正因为returnThreadInfo是一个线程,所以run方法并不一定在 System.out.println(returnThreadInfo.getThreadInfo())之前运行。因为实际上主类Main在运行时 也是一个线程,当调用returnThreadInfo.start()方法来启动returnThreadInfo线程后,此时系统中运行的实际上就是 Main和returnThreadInfo两个线程,那么这两个线程就会竞争CPU,谁先抢到CPU的控制权,谁就会先运行(实际上线程谁能优先抢到 CPU运行时间是靠优先级来决定的,优先级可以通过线程的setPriority(int newPriority)来设置,newPriority的取值是1-10,newPriority值越大,线程的优先级就越高,优先强占CPU的几率就 越大。线程默认的优先级是5)。由于Main和returnThreadInfo的优先级都默认为5,所以它们争抢CPU的几率是相同的。又因为Main 线程实际上是比returnThreadInfo线程先启动的,所以在这个程序中,Main的 System.out.println(returnThreadInfo.getThreadInfo())反而比returnThreadInfo的 run方法更早运行,所以输出的str值还是初始的"Hello"。

  2、误区二:认为线程运行完毕后,线程消亡的同时,线程对象也会一并被回收。

  下面对ReturnThreadInfo类的源代码进行修改,将ReturnThreadInfo线程的优先级设置为10:

public ReturnThreadInfo() {
    this.str = "Hello";
this.setPriority(10);
}

   这样returnThreadInfo线程的run()方法就会在Main类的 System.out.println(returnThreadInfo.getThreadInfo())语句之前被运行。因此有很多人会认为当 returnThreadInfo线程的run()方法运行完毕并返回后,线程就会死亡,那么Main类的最后一句 System.out.println(returnThreadInfo.getThreadInfo())就会出问题,等于调用了已经不存在的对 象:returnThreadInfo。

  实际上这存在着很大的一个误区,线程的死亡并不意味着线程对象的销毁和回收。线程的死亡指的是 当线程的run方法结束后,该线程就无法被重用和启动,但它的对象还存在并且它的属性和方法还一样可以被使用,因此 System.out.println(returnThreadInfo.getThreadInfo())输出的并不是NULL而是"Hello World!",只有当整个应用程序都结束后,returnThreadInfo对象才会被销毁和回收。

分享到:
评论

相关推荐

    线程 JAVA java线程 java线程第3版 java线程第2版第3版合集

    电子书相关:包含4个有关JAVA线程的电子书(几乎涵盖全部有关线程的书籍) OReilly.Java.Threads.3rd.Edition.Sep.2004.eBook-DDU Java Thread Programming (Sams) java线程第二版中英文 java线程第二版中英文 ...

    java 线程工具类 java 线程工具类

    java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具类 java 线程工具类java 线程工具...

    启动两个线程,一个线程打印1~52,另一个线程打印A~Z

    启动两个线程,一个线程打印1~52,另一个线程打印A~Z

    关于线程(java)两天的课件

    此外,死锁是多线程编程中常见的问题,当两个或更多的线程互相等待对方释放资源时就会发生。避免死锁的关键在于遵循死锁预防的四个条件:互斥、请求与保持、不剥夺和循环等待。Java提供了一些工具如jstack和VisualVM...

    JAVA 多线程.7z

    死锁是两个或更多线程相互等待对方释放资源而无法继续执行的情况。活锁则是线程虽然没有被阻塞,但不断重试导致无法前进。避免死锁和活锁的方法包括避免循环等待、设置超时、正确使用锁顺序等。 七、线程优先级 ...

    Java实现的两个线程同时运行案例

    Java多线程编程实现两个线程同时运行案例 Java多线程编程是Java编程中的一种重要技术,用于实现多任务并发执行,提高程序的执行效率和响应速度。在本文中,我们将介绍如何使用Java实现两个线程同时运行的案例,涉及...

    java线程.pdf

    一个标准的Java应用程序至少会有一个线程,即主线程,用于执行程序的主要逻辑。通过创建多个线程,可以实现并发执行任务,提高程序的运行效率和响应速度。线程在Java中可以通过两种方式创建:继承`Thread`类或者实现...

    Java线程详解大全

    Java线程是并发编程的核心部分,它允许程序在同一时间执行多个独立的任务,从而提高系统效率和响应速度。本文将深入探讨Java线程的概念、生命周期、实现方式以及相关的同步机制。 首先,理解线程的基本概念至关重要...

    Java线程使用教程

    1. **死锁**:两个或多个线程相互等待对方释放资源,导致无法继续执行的状态。避免死锁的关键在于正确设计资源的获取顺序。 2. **活锁**:线程不断地尝试获取资源但始终不成功,造成系统资源的浪费。可以通过超时或...

    java多线程Demo

    在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新的类,让它继承Thread类时,可以通过重写`run()`方法来定义线程执行的任务。然后创建该类的对象,并...

    java 线程 dump 分析工具 2.3.3

    Java的TDA线程转储分析器是一个用于分析Sun Java VM生成的线程转储和堆信息的小型Swing GUI(目前用1.4测试)。它从提供的日志文件中解析线程转储和类直方图。它提供关于发现的线程转储的统计信息,提供关于锁定监视器...

    java用线程两种方式

    在这个main方法中,程序通过两种方式创建了两个线程:一个打印1到1000之间的所有奇数,另一个打印所有偶数。通过使用while循环,程序会持续运行直到两个线程都完成了它们的任务。 总结来说,Java通过两种方式提供了...

    java线程深入解析

    创建Java线程有两种方式:继承`Thread`类并重写`run()`方法,或者实现`Runnable`接口并提供`run()`方法。当线程对象被创建并调用`start()`方法后,线程进入可运行态,由Java的线程调度器决定何时执行`run()`方法。 ...

    电子书《java线程》

    6. **死锁**:当两个或更多线程相互等待对方释放资源时,可能会出现死锁现象,学习如何预防和解决死锁是重要的。 7. **线程优先级**:虽然Java提供了线程优先级,但在多核系统中并不保证优先级高的线程先执行,因此...

    java 线程相关工具类

    java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类.java 线程相关工具类....

    JAVA线程学习(源代码)

    死锁是多线程编程中的常见问题,当两个或更多线程互相等待对方释放资源,导致所有线程都停止运行,就形成了死锁。避免死锁的关键在于正确设计资源的获取顺序和避免循环等待。 在Java中,线程间的通信可以通过wait()...

    JAVA线程dump的分析

    JAVA线程dump的分析 JAVA线程dump是指在JAVA程序中,当前线程的状态和调用堆栈的快照,能够帮助开发者了解当前程序的执行情况,诊断问题和性能瓶颈。生成JAVA线程dump的方法在不同的操作系统下是不同的,在Windows...

    java线程文档大全

    2. **线程创建**:Java提供两种方式创建线程,一是直接继承Thread类并重写run()方法,二是实现Runnable接口并定义run()方法,然后通过Thread类的构造函数将Runnable对象传递进去。 3. **线程交互**:线程之间的通信...

    Java多线程设计模式上传文件

    Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式上传文件Java多线程设计模式...

    java多线程编程 在主线程main中创建两个子线程

    自己学着编写的一个JAVA多线程程序,该程序实现的功能是:在主线程main中创建两个子线程,A和B,线程A先运行,再运行B线程,当两个子线程都运行完毕后,才运行主线程,并最终结束整个程序的运行。 希望该程序对初学...

Global site tag (gtag.js) - Google Analytics