【深入分析JAVA多线程】(2)Java多线程基本概念和常用方法分析

    xiaoxiao2021-12-14  19

     

    Thread类和Runnable接口

    1、Thread类

    在JAVA APIDOCS中,Thread类有这样一段话:  线程 是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程。  每个线程都有一个优先级,高优先级线程的执行优先于低优先级线程。每个线程都可以或不可以标记为一个守护程序。当某个线程中运行的代码创建一个新 Thread 对象时,该新线程的初始优先级被设定为创建线程的优先级,并且当且仅当创建线程是守护线程时,新线程才是守护程序。  当 Java 虚拟机启动时,通常都会有单个非守护线程(它通常会调用某个指定类的 main 方法)。Java 虚拟机会继续执行线程,直到下列任一情况出现时为止:  调用了 Runtime 类的 exit 方法,并且安全管理器允许退出操作发生。  非守护线程的所有线程都已停止运行,无论是通过从对 run 方法的调用中返回,还是通过抛出一个传播到 run 方法之外的异常。

    创建线程时,必须使用该类。该类封装了线程的行为。

    2、Runnable接口

    API中的解释是:

    Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。  设计该接口的目的是为希望在活动时执行代码的对象提供一个公共协议。例如,Thread 类实现了 Runnable。激活的意思是说某个线程已启动并且尚未停止。  此外,Runnable 为非 Thread 子类的类提供了一种激活方式。通过实例化某个 Thread 实例并将自身作为运行目标,就可以运行实现 Runnable 的类而无需创建 Thread 的子类。大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类创建子类。

    这段解释已经将Runnable的作用说的十分清楚了。

    3、创建、启动线程及注意事项

    (1)JAVA中创建线程有两种方式:  1)通过继承Thread类,通常应该重写其run方法,将线程运行的逻辑放在其中。因为Thread中的run方法是一个空实现。  2)通过实现Runnable接口,然后通过实例化一个Thread实例并将自身作为运行目标。

    那么在使用中,应该使用那种方式呢?当然使用哪种方式都行,然而在Runnable接口API文档中已经详细地说明该如何选择这两种方式:大多数情况下,如果只想重写 run() 方法,而不重写其他 Thread 方法,那么应使用 Runnable 接口。这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应为该类(Thread)创建子类。

    在第二种方式中,经常会使用内部类的方式来使用。

    (2)启动线程  因为run方法是不能显示调用的,启动一个线程不是调用run方法,而是调用Thread类的start方法。

    启动线程大概有以下五种方式:

    线程启动方式  当然提供名称并非必须的,因为如果不指定名称,系统会自动生成一个名称,自动生成的名称的形式为 “Thread-“+n,其中的 n 为整数。

    interrupt()、interrupted()、isInterrupted()

    1、interrupt  interrupt方法用于中断线程。调用该方法的线程的状态为将被置为”中断”状态。  注意:线程中断仅仅是置线程的中断状态位,不会停止线程。需要用户自己去监视线程的状态为并做处理。支持线程中断的方法(也就是线程中断后会抛出interruptedException的方法)就是在监视线程的中断状态,一旦线程的中断状态被置为“中断状态”,就会抛出中断异常。

    2、interrupted 和 isInterrupted

    首先看一下该方法的实现:

    public static boolean interrupted () { return currentThread().isInterrupted(true); }

    该方法就是直接调用当前线程的isInterrupted(true)方法。  然后再来看一下 isInterrupted的实现:

    public boolean isInterrupted () { return isInterrupted( false); }

    这两个方法有两个主要区别:

    interrupted 是作用于当前线程,isInterrupted 是作用于调用该方法的线程对象所对应的线程。(线程对象对应的线程不一定是当前运行的线程。例如我们可以在A线程中去调用B线程对象的isInterrupted方法。这两个方法最终都会调用同一个方法,只不过参数一个是true,一个是false;

    第二个区别主要体现在调用的方法的参数上,让我们来看一看这个参数是什么含义

    先来看一看被调用的方法 isInterrupted(boolean arg)的定义:

    private native boolean isInterrupted( boolean ClearInterrupted);

    原来这是一个本地方法,看不到源码。不过没关系,通过参数名我们就能知道,这个参数代表是否要清除状态位。  如果这个参数为true,说明返回线程的状态位后,要清掉原来的状态位(恢复成原来情况)。这个参数为false,就是直接返回线程的状态位。  这两个方法很好区分,只有当前线程才能清除自己的中断位(对应interrupted()方法)

    是不是这样理解呢  Thread.currentThread().interrupt(); 这个用于清除中断状态,这样下次调用Thread.interrupted()方法时就会一直返回为true,因为中断标志已经被恢复了。  而调用isInterrupted 只是简单的查询中断状态,不会对状态进行修改。

    interrupt()是用来设置中断状态的。  返回true说明中断状态被设置了而不是被清除了。  我们调用sleep、wait等此类可中断(throw InterruptedException)方法时,一旦方法抛出InterruptedException,当前调用该方法的线程的中断状态就会被jvm自动清除了,就是说我们调用该线程的isInterrupted 方法时是返回false。  如果你想保持中断状态,可以再次调用interrupt方法设置中断状态。这样做的原因是,java的中断并不是真正的中断线程,而只设置标志位(中断位)来通知用户。如果你捕获到中断异常,说明当前线程已经被中断,不需要继续保持中断位。

    interrupted是静态方法,返回的是当前线程的中断状态。  例如,如果当前线程被中断(没有抛出中断异常,否则中断状态就会被清除),你调用interrupted方法,第一次会返回true。  然后,当前线程的中断状态被方法内部清除了。第二次调用时就会返回false。如果你刚开始一直调用isInterrupted,则会一直返回true,除非中间线程的中断状态被其他操作清除了。

    yield()、suspend()、resume()、stop()

    sleep():允许指定以毫秒为单位的一段时间作为参数,它使得线程在指定的时间内进入阻塞状态,不能得到CPU 时 间,指定的时间一过,线程重新进入可执行状态。典型地,sleep() 被用在等待某个资源就绪的情形:测试发现条件不满足后,让线程阻塞一段时间后重新 测试,直到条件满足为止。

    suspend()&resume():两个方法配套使用,suspend()使得线程进 入阻塞状态,并且不会自动恢复,必须其对应的resume() 被调用,才能使得线程重新进入可执行状态。典型 地,suspend() 和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果 后,调用 resume() 使其恢复。  suspend()和resume()必须要成对出现,否则非常容易发生死锁。  因为suspend方法并不会释放锁,如果使用suspend的目标线程对一个重要的系统资源持有锁,那么没任何线程可以使用这个资源直到要suspend的目标线程被resumed,如果一个线程在resume目标线程之前尝试持有这个重要的系统资源锁再去resume目标线程,这两条线程就相互死锁了,也就冻结线程。

    yield():yield() 使得线程放弃当前分得的 CPU 时间,但是不使线程阻塞,即线程仍处于可执行状态,随时可能再次分得 CPU 时间。调用 yield() 的效果等价于调度程序认为该Java线程同步已执行了足够的时间从而转到另一个线程。当调用stop()方法时会发生两件事:  即刻停止run()方法中剩余的全部工作,包括在catch或finally语句中,并抛出ThreadDeath异常(通常情况下此异常不需要显示的捕获),因此可能会导致一些清理性的工作的得不到完成,如文件,数据库等的关闭。会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题。

    欢迎关注公众号:

    转载请注明原文地址: https://ju.6miu.com/read-971864.html

    最新回复(0)