Java 多线程
-
多线程
在讨论多线程之前,让我们讨论线程。线程是进程的轻量级最小部分,可以与同一进程的其他部分(其他线程)同时运行。线程是独立的,因为它们都具有独立的执行路径,这就是一个线程中发生异常的原因,它不会影响其他线程的执行。进程的所有线程共享公共内存。同时执行多个线程的过程称为多线程。让我们总结一下要点:1.多线程的主要目的是提供程序的两个或更多部分的同时执行,以最大程度地利用CPU时间。多线程程序包含两个或多个可以同时运行的部分。程序的每个这样的部分称为线程。2.线程是轻量级子进程,它们共享公共内存空间。在多线程环境中,受益于多线程的程序会最大利用的CPU时间,以便将空闲时间保持为最小(别让CPU闲着无事,蛋疼)。3.线程可以处于以下状态之一:- NEW – 尚未启动的线程处于此状态。
- RUNNABLE – 在Java虚拟机中执行的线程处于这种状态。
- BLOCKED – 等待监视器锁定而被阻塞的线程处于此状态。
- WAITING – 无限期地等待另一个线程执行特定操作的线程处于此状态。
- TIMED_WAITING – 正在等待另一个线程执行操作的线程最多达到指定的等待时间,该线程处于此状态。
- TERMINATED – 退出的线程处于此状态。
在给定的时间点,线程只能处于一种状态。线程的生命周期如下图所示: -
多任务,多线程,多进程,并行处理
让我们举个例子来更好地理解这些概念:此类实现Serializable接口,这意味着可以对其进行序列化。此类中的所有字段都可以在转换为字节流之后写入文件中,除非那些字段声明为transient。在下面的示例中,我们有两个临时字段,这些字段将不参与序列化。如果您不熟悉Java,可能会在这些术语之间感到困惑,因为在我们讨论多线程时,它们经常被使用。 让我们简单地谈谈它们。- 多任务:能够同时执行多个任务的能力称为多任务。
- 多线程:我们已经讨论过了。 它是同时执行多个线程的过程。 多线程也称为基于线程的多任务。
- 多进程:与多任务处理相同,但是在多处理中涉及多个CPU。 另一方面,一个CPU参与多任务处理。
- 并行处理:它是指在单个计算机系统中使用多个CPU。
-
用Java创建线程
这是使用Java创建线程的两种方法:- 通过继承Thread类。
- 通过实现Runnable接口。
在开始创建线程的程序(代码)之前,让我们看一下Thread类的这些方法。 在下面的示例中,我们很少使用这些方法。- getName():用于获取线程的名称
- getPriority():获取线程的优先级
- isAlive():确定线程是否仍在运行
- join():等待线程终止
- run():线程的入口点
- sleep():将线程暂停一段时间
- start():通过调用其run()方法启动线程
方法1:通过继承Thread类创建线程输出如下:提示:多运行几次,每次输出的结果不一定相同,CPU内部在这循环十次中切换线程的点有可能是不同的。
方法2:通过实现Runnable接口创建线程下面来看一个复杂点的例子,观察该程序的输出,并尝试了解该程序中正在发生的事情。 如果您了解每种线程方法的用法,那么理解此示例就不会遇到任何问题。输出:提示:多运行几次,每次输出的结果不一定相同,CPU内部在这循环十次中切换线程的点有可能是不同的。
-
线程优先级
- 线程优先级是整数,它决定相对于其他线程应如何对待一个线程。
- 线程优先级决定何时从一个正在运行的线程切换到另一线程,此过程称为上下文切换
- 线程可以自愿释放控制权,并且把控制权交给已准备好运行的最高优先级线程。
- 不管低优先级线程在做什么,都可以由高优先级线程抢占该线程。每当更高优先级的线程要运行时,它都会运行。
- 为了设置线程的优先级,使用ThreadClass类的setPriority()方法。
- 在发生在整数定义优先级的,我们可以使用MIN_PRIORITY,NORM_PRIORITY或MAX_PRIORITY。
-
方法:isAlive()和join()
- 在所有实际情况下,主线程应最后完成,否则从主线程派生的其他线程也应完成。
- 要知道线程是否已完成,我们可以调用isAlive()线程,如果线程未完成,则返回true。
- 通过使用join()方法来实现此目的的另一种方法,当从父线程调用此方法时,该方法会使父线程等待直到子线程终止。
- 这些方法在Thread类中定义。
-
同步化
- 多线程将异步行为引入程序。如果一个线程正在写入某些数据,那么另一个线程可能正在读取同一数据。这可能会导致不一致。
- 当两个或多个线程需要访问共享资源时,应采用某种方式一次仅将一个线程使用该资源。实现此目的的过程称为同步。
- 为了实现同步行为,java具有同步方法。一旦线程在同步方法中,则其他任何线程都无法在同一对象上调用任何其他同步方法。然后,所有其他线程等待,直到第一个线程从同步块中出来。
- 当我们要同步对不是为多线程访问设计的类的对象的访问,并且我们无法使用需要同步访问的方法的代码时,在这种情况下,我们无法将同步添加到适当的方法中。在Java中,我们有解决方案,可以通过以下方式将对此类定义的方法的调用(需要同步)放入同步块中。
-
线程间通讯
我们几乎没有方法可以通过java线程相互通信。这些方法是wait(),notify(),notifyAll()。所有这些方法只能从Synchronized方法中调用。- 要了解同步,Java具有监视器的概念。可以将监视器视为只能容纳一个线程的盒子。线程进入监视器后,所有其他线程必须等待,直到该线程退出监视器。
- wait()告诉调用线程放弃监视器并进入睡眠状态,直到其他某个线程进入同一监视器并进行调用notify()。
- notify()唤醒wait()在同一对象上调用的第一个线程。
- notifyAll()唤醒同一对象上所有调用wait()的线程。优先级最高的线程将首先运行。