Java Thread 多线程 操作线程

简介:
创建、启动线程
线程的实现方式
线程的生命周期
线程的状态
控制线程
 
5、线程的创建和启动
    A、继承Thread类或实现Runnable接口,重写或实现run方法,run方法代表线程要完成的任务
    B、创建Thread子类或是Runnable的实现类,即创建的线程对象;不同的是接口实现线程,
        需要将接口的实现类作为参数传递给Thread类的构造参数
    C、用线程对象的start方法启动线程
 
6、继承Thread和实现Runnable接口创建线程的区别
    采用Runnable接口实现线程:
    优势:
        A、线程类只是实现了Runnable接口,还可以继承其他的类
        B、在这种方式下,可以多个线程共享同一个目标对象,所以很合适多个线程来处理同一份资源的情况,
            从而可以将CPU、代码和数据分开,形成清晰的模型,较好的面相对象思想。
    劣势:编程稍微复杂,如果需要访问当前线程需要用Thread.currentThread方法来获取
 
    采用继承Thread类的方式实现线程:
    优势:编写简单,如果要获得当前线程直接this即可
    劣势:线程类继承了Thread,不能在继承其他类
    相对而言,用Runnable的方式更好,具体可以根据当前需要而定;
 
7、线程生命周期
    线程被创建启动后,不并不是启动后就进入了执行状态,也不是一直处于的执行状态。
    线程的生命周期分为创建(new)、就绪(Runnable)、运行(running)、阻塞(Blocked)、死亡(Dead)五种状态。
    线程启动后不会一直霸占CPU资源,所以CPU需要在多条线程中切换执行,线程就会在多次的运行和阻塞中切换。
 
8、新建(new)和就绪(Runnable)状态
    当new一个线程后,该线程处于新建状态,此时它和Java对象一样,仅仅由Java虚拟机为其分配内存空间,并初始化成员变量。
    此时线程对象没有表现出任何的动态特征,程序也不会执行线程的执行体。
    注意:run方法是线程的执行体,不能由我们手动调用。我们可以用start方法启动线程,系统会把run方法当成线程的执行体来运行,
    如果直接调用线程对象run方法,则run方法立即会被运行。而且在run方法返回之前其他线程无法并行执行,
    也就是说系统会把当前线程类当成一个普通的Java对象,而run方法也是一个普通的方法,而不是线程的执行体。
 
9、运行(running)和阻塞(Blocked)状态
    如果处于就绪状态的线程就获得了CPU,开始执行run方法的线程执行体,则该线程处于运行状态。
    单CPU的机器,任何时刻只有一条线程处于运行状态。当然,在多CPU机器上将会有多线程并行(parallel)执行,
    当线程大于CPU数量时,依然会在同一个CPU上切换执行。
    线程运行机制:一个线程运行后,它不可能一直处于运行状态(除非它执行的时间很短,瞬间执行完成),线程在运行过程中需要中断,
    目的是让其他的线程有运行机会,线程的调度取决于底层的策略。对应抢占式的系统而言,系统会给每个可执行的线程一个小时间段来处理任务,
    当时间段到达系统就会剥夺该线程的资源,让其他的线程有运行的机会。在选择下一个线程时,系统会考虑线程优先级。
    以下情况会出现线程阻塞状态:
        A、线程调用sleep方法,主动放弃占用的处理器资源
        B、线程调用了阻塞式IO方法,在该方法返回前,该线程被阻塞
        C、线程试图获得一个同步监视器,但该同步监视器正被其他线程所持有。
        D、线程等待某个通知(notify)
        E、程序调用了suspend方法将该线程挂起。不过这个方法容易导致死锁,尽量不免使用该方法
    当线程被阻塞后,其他线程将有机会执行。被阻塞的线程会在合适的时候重新进入就绪状态,注意是就绪状态不是运行状态。
    也就是被阻塞线程在阻塞解除后,必须重新等待线程调度器再次调用它。
    针对上面线程阻塞的情况,发生以下特定的情况可以解除阻塞,让进程进入就绪状态:
        A、调用sleep方法的经过了指定的休眠时间
        B、线程调用的阻塞IO已经返回,阻塞方法执行完毕
        C、线程成功获得了试图同步的监视器
        D、线程正在等待某个通知,其他线程发出了通知
        E、处于挂起状态的线程调用了resume恢复方法
    线程从阻塞状态只能进入就绪状态,无法进入运行状态。而就绪和运行状态之间的转换通常不受程序控制,而是由系统调度所致的。
    当就绪状态的线程获得资源时,该线程进入运行状态;当运行状态的线程事情处理器资源时就进入了就绪状态。
    但对调用了yield的方法就例外,此方法可以让运行状态转入就绪状态。
 
10、线程死亡(Dead)状态
    线程会在以下方式进入死亡状态:
    A、run方法执行完成,线程正常结束
    B、线程抛出未捕获的异常或Error
    C、直接调用该线程的stop方法来结束线程—该方法易导致死锁,注意使用
    注意:当主线程结束的时候,其他线程不受任何影响。一旦子线程启动后,会拥有和主线程相同的地位,不受主线程影响。
    isAlive方法可以测试当前线程是否死亡,当线程处于就绪、运行、阻塞状态,该方法返回true,如果线程处于新建或死亡状态就会返回false。
    不要试图对死亡的线程调用start方法,来启动它。死亡线程不可能再次运行。
 
11、控制线程
    Java线程提供了很多工具方法,这些方法都很好的控制线程
    A、join线程
        让一个线程等待另一个线程完成的方法。当某个程序执行流中调用其他线程的join方法时,调用线程将会被阻塞,直到被join方法的join线程执行完成为止。
        join方法通常有使用线程的程序调用,将大问题划分成许多小问题。每个小问题分配一个线程。当所有的小问题得到处理后,再调用主线程进一步操作。
        join有三种重载模式:
            一、join等待被join的线程执行完成
            二、join(long millis)等待被join的线程时间最长为millis毫秒,如果在millis毫秒外,被join的线程还没有执行完则不再等待
            三、join(long millis, int nanos)被join的线程等待时间长为millis毫秒加上nanos微秒
        通常我们很少用第三种join,原因有二:程序对时间的精度无需精确到千分之一毫秒
        计算机硬件、操作系统也无法做到精确到千分之一毫秒
    
    B、后台线程
        有一种线程,在后台运行,它的任务是为其他线程提供服务,这种线程被称为“后台线程(Daemon Thread)”,有被称为“守护线程”或“精灵线程”。
        JVM的垃圾回收器线程就是后台进程。
        后台进程有个特征是:如果前台的进程都死亡,那么后台进程也死亡。(它为前台进程服务)
        用Thread的setDaemon (true)方法可以指定当前线程为后台线程。
        注意:前台线程执行完成死亡后,JVM会通知后台线程,后台线程就会死亡。但它得到通知到后台线程作成响应,需要一段时间,
        而且要将某个线程设置为后台线程,必需要在该线程启动前设置,也就是说设置setDaemon必需在start方法前面调用。
        否则会出现java.lang.IllegalThreadStateException异常
    
    C、线程休眠sleep
        如果需要当前线程暂停一段时间,并进入阻塞状态就需要用sleep,sleep有2中重载方式:
        sleep(long millis)让当前线程暂停millis毫秒后,并进入阻塞状态,该方法受系统计时器和线程调度器的影响
        sleep(long millis, int nanos)让当前正在执行的线程暂停millis毫秒+nanos微秒,并进入阻塞
        当调用sleep方法进入阻塞状态后,在sleep时间段内,该线程不会获得执行机会,即使没有其他可运行的线程,处于sleep的线程不会执行。
 
    D、线程让步yield
        yield和sleep有点类似,它也可以让当前执行的线程暂停,但它不会阻塞线程,只是将该线程转入到就绪状态。
        yield只是让当前线程暂停下,让系统线程调度器重新调度下。
        当yield的线程后,当前线程暂停。系统线程调度器会让优先级相同或是更高的线程运行。
        
        sleep和yield的区别
            (1)、sleep方法暂停当前线程后,会给其他线程执行集合,不会理会线程的优先级。但yield则会给优先级相同或高优先级的线程执行机会
            (2)、sleep方法会将线程转入阻塞状态,直到经过阻塞时间才会转入到就绪状态;而yield则不会将线程转入到阻塞状态,它只是强制当前线程进入就绪状态。
                    因此完全有可能调用yield方法暂停之后,立即再次获得处理器资源继续运行。
            (3)、sleep声明抛出了InterruptedException异常,所以调用sleep方法时,要么捕获异常,要么抛出异常。而yield没有申明抛出任何异常
        
    E、改变线程优先级
        每个线程都有优先级,优先级决定线程的运行机会的多少。
        每个线程默认和它创建的父类的优先级相同,main方法的优先级是普通优先级,那在main方法中创建的子线程都是普通优先级。
        getPriority(int newPriority)/setPriority(int)
        设置优先级有以下级别:
            MAX_PRIORITY 值是10
            MIN_PRIORITY 值是1
            NORM_PRIORITY 值是5
            范围是1-10;






本文转自hoojo博客园博客,原文链接:http://www.cnblogs.com/hoojo/archive/2011/05/05/2038070.html,如需转载请自行联系原作者
目录
相关文章
|
2天前
|
Java 调度
[Java]线程生命周期与线程通信
本文详细探讨了线程生命周期与线程通信。文章首先分析了线程的五个基本状态及其转换过程,结合JDK1.8版本的特点进行了深入讲解。接着,通过多个实例介绍了线程通信的几种实现方式,包括使用`volatile`关键字、`Object`类的`wait()`和`notify()`方法、`CountDownLatch`、`ReentrantLock`结合`Condition`以及`LockSupport`等工具。全文旨在帮助读者理解线程管理的核心概念和技术细节。
13 1
[Java]线程生命周期与线程通信
|
22小时前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
16 4
|
20小时前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
14 3
|
22小时前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
14 2
|
22小时前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
64 38
|
2天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
3天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
8 2
|
3天前
|
Java
在Java多线程编程中,实现Runnable接口通常优于继承Thread类
【10月更文挑战第20天】在Java多线程编程中,实现Runnable接口通常优于继承Thread类。原因包括:1) Java只支持单继承,实现接口不受此限制;2) Runnable接口便于代码复用和线程池管理;3) 分离任务与线程,提高灵活性。因此,实现Runnable接口是更佳选择。
10 2
|
3天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
10 2
|
6月前
|
存储 安全 Java
深入理解Java并发编程:线程安全与锁机制
【5月更文挑战第31天】在Java并发编程中,线程安全和锁机制是两个核心概念。本文将深入探讨这两个概念,包括它们的定义、实现方式以及在实际开发中的应用。通过对线程安全和锁机制的深入理解,可以帮助我们更好地解决并发编程中的问题,提高程序的性能和稳定性。