Java 教程
- Java - 首页
- Java - 概述
- Java - 历史
- Java - 特性
- Java 与 C++
- JVM - Java 虚拟机
- Java - JDK vs JRE vs JVM
- Java - Hello World 程序
- Java - 环境搭建
- Java - 基本语法
- Java - 变量类型
- Java - 数据类型
- Java - 类型转换
- Java - Unicode 系统
- Java - 基本运算符
- Java - 注释
- Java - 用户输入
- Java - 日期与时间
Java 控制语句
- Java - 循环控制
- Java - 决策制定
- Java - If-else
- Java - Switch
- Java - For 循环
- Java - For-Each 循环
- Java - While 循环
- Java - do-while 循环
- Java - Break
- Java - Continue
面向对象编程
- Java - OOPs 概念
- Java - 对象与类
- Java - 类属性
- Java - 类方法
- Java - 方法
- Java - 变量作用域
- Java - 构造方法
- Java - 访问修饰符
- Java - 继承
- Java - 聚合
- Java - 多态
- Java - 重写
- Java - 方法重载
- Java - 动态绑定
- Java - 静态绑定
- Java - 实例初始化块
- Java - 抽象
- Java - 封装
- Java - 接口
- Java - 包
- Java - 内部类
- Java - 静态类
- Java - 匿名类
- Java - 单例类
- Java - 包装类
- Java - 枚举
- Java - 枚举构造方法
- Java - 枚举字符串
Java 内置类
Java 文件处理
Java 错误与异常
- Java - 异常
- Java - try-catch 块
- Java - try-with-resources
- Java - 多重捕获块
- Java - 嵌套 try 块
- Java - Finally 块
- Java - throw 异常
- Java - 异常传播
- Java - 内置异常
- Java - 自定义异常
Java 多线程
- Java - 多线程
- Java - 线程生命周期
- Java - 创建线程
- Java - 启动线程
- Java - 线程连接
- Java - 线程命名
- Java - 线程调度器
- Java - 线程池
- Java - 主线程
- Java - 线程优先级
- Java - 守护线程
- Java - 线程组
- Java - 关闭钩子
Java 同步
Java 网络
- Java - 网络
- Java - 套接字编程
- Java - URL 处理
- Java - URL 类
- Java - URLConnection 类
- Java - HttpURLConnection 类
- Java - Socket 类
- Java - 泛型
Java 集合
Java 接口
Java 数据结构
Java 集合算法
高级 Java
- Java - 命令行参数
- Java - Lambda 表达式
- Java - 发送邮件
- Java - Applet 基础
- Java - Javadoc 注释
- Java - 自动装箱和拆箱
- Java - 文件不匹配方法
- Java - REPL (JShell)
- Java - 多版本 Jar 文件
- Java - 私有接口方法
- Java - 内部类菱形运算符
- Java - 多分辨率图像 API
- Java - 集合工厂方法
- Java - 模块系统
- Java - Nashorn JavaScript
- Java - Optional 类
- Java - 方法引用
- Java - 函数式接口
- Java - 默认方法
- Java - Base64 编码解码
- Java - Switch 表达式
- Java - Teeing 收集器
- Java - 微基准测试
- Java - 文本块
- Java - 动态 CDS 归档
- Java - Z 垃圾收集器 (ZGC)
- Java - 空指针异常
- Java - 打包工具
- Java - 密封类
- Java - 记录类
- Java - 隐藏类
- Java - 模式匹配
- Java - 简洁数字格式化
- Java - 垃圾回收
- Java - JIT 编译器
Java 杂项
- Java - 递归
- Java - 正则表达式
- Java - 序列化
- Java - 字符串
- Java - 进程 API 改进
- Java - 流 API 改进
- Java - 增强的 @Deprecated 注解
- Java - CompletableFuture API 改进
- Java - 流
- Java - 日期时间 API
- Java 8 - 新特性
- Java 9 - 新特性
- Java 10 - 新特性
- Java 11 - 新特性
- Java 12 - 新特性
- Java 13 - 新特性
- Java 14 - 新特性
- Java 15 - 新特性
- Java 16 - 新特性
Java API 和框架
Java 类参考
- Java - Scanner
- Java - 数组
- Java - 字符串
- Java - Date
- Java - ArrayList
- Java - Vector
- Java - Stack
- Java - PriorityQueue
- Java - LinkedList
- Java - ArrayDeque
- Java - HashMap
- Java - LinkedHashMap
- Java - WeakHashMap
- Java - EnumMap
- Java - TreeMap
- Java - IdentityHashMap
- Java - HashSet
- Java - EnumSet
- Java - LinkedHashSet
- Java - TreeSet
- Java - BitSet
- Java - Dictionary
- Java - Hashtable
- Java - Properties
- Java - Collection
- Java - Array
Java 有用资源
Java - 多线程
Java 是一种多线程编程语言,这意味着我们可以使用 Java 开发多线程程序。多线程程序包含两个或多个可以并发运行的部分,并且每个部分可以同时处理不同的任务,从而充分利用可用资源,尤其是在您的计算机有多个CPU时。
根据定义,多任务处理是指多个进程共享 CPU 等公共处理资源。多线程将多任务处理的概念扩展到应用程序中,在应用程序中,您可以将单个应用程序内的特定操作细分为单独的线程。每个线程都可以并行运行。操作系统不仅在不同的应用程序之间分配处理时间,而且在应用程序内的每个线程之间分配处理时间。
Java 多线程
多线程使您能够以一种方式编写代码,在该代码中,多个活动可以在同一程序中并发进行。为了实现多线程(或编写多线程代码),您需要java.lang.Thread 类。
Java 多线程中线程的生命周期
线程在其生命周期中会经历各个阶段。例如,线程诞生、启动、运行,然后死亡。下图显示了线程的完整生命周期。
以下是生命周期的阶段:
新建 - 新线程从新建状态开始其生命周期。它保持在此状态,直到程序启动线程。它也称为新生线程。
可运行 - 新生线程启动后,线程变为可运行状态。处于此状态的线程被认为正在执行其任务。
等待 - 有时,线程在等待另一个线程执行任务时会过渡到等待状态。线程仅在另一个线程发出信号让等待线程继续执行时才返回到可运行状态。
计时等待 - 可运行线程可以在指定的时间间隔内进入计时等待状态。处于此状态的线程在该时间间隔到期或其等待的事件发生时返回到可运行状态。
终止(死亡) - 可运行线程在完成其任务或以其他方式终止时进入终止状态。
线程优先级
每个 Java 线程都有一个优先级,它可以帮助操作系统确定线程的调度顺序。
Java 线程优先级范围在 MIN_PRIORITY(常量 1)和 MAX_PRIORITY(常量 10)之间。默认情况下,每个线程都分配了 NORM_PRIORITY(常量 5)的优先级。
优先级较高的线程对程序更重要,应在优先级较低的线程之前分配处理器时间。但是,线程优先级不能保证线程执行的顺序,并且在很大程度上取决于平台。
通过实现 Runnable 接口创建线程
如果您的类旨在作为线程执行,那么您可以通过实现Runnable接口来实现。您需要遵循三个基本步骤:
步骤 1:实现 run() 方法
第一步,您需要实现Runnable接口提供的 run() 方法。此方法为线程提供了一个入口点,您将在其中放置完整的业务逻辑。以下是 run() 方法的简单语法:
public void run( )
步骤 2:实例化 Thread 对象
第二步,您将使用以下构造函数实例化Thread对象:
Thread(Runnable threadObj, String threadName);
其中,threadObj是实现Runnable接口的类的实例,threadName是赋予新线程的名称。
步骤 3:使用 start() 方法调用线程
创建 Thread 对象后,您可以通过调用start()方法启动它,该方法会执行对 run( ) 方法的调用。以下是 start() 方法的简单语法:
void start();
示例:通过实现 Runnable 接口创建线程
这是一个创建新线程并开始运行它的示例:
class RunnableDemo implements Runnable { private Thread t; private String threadName; RunnableDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while. Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } }
输出
Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, 4 Running Thread-2 Thread: Thread-2, 4 Thread: Thread-1, 3 Thread: Thread-2, 3 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-1, 1 Thread: Thread-2, 1 Thread Thread-1 exiting. Thread Thread-2 exiting.
通过扩展 Thread 类创建线程
创建线程的第二种方法是创建一个扩展Thread类的新的类,使用以下两个简单的步骤。这种方法在处理使用Thread类中可用方法创建的多个线程时提供了更大的灵活性。
步骤 1:重写 run() 方法
您需要重写Thread类中可用的run( )方法。此方法为线程提供了一个入口点,您将在其中放置完整的业务逻辑。以下是run()方法的简单语法:
public void run( )
步骤 2:使用 start() 方法调用线程
创建Thread对象后,您可以通过调用start()方法启动它,该方法会调用run( )方法。以下是start()方法的简单语法:
void start( );
示例:通过扩展Thread类创建线程
以下是前面程序重写为扩展Thread的示例:
class ThreadDemo extends Thread { private Thread t; private String threadName; ThreadDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // Let the thread sleep for a while. Thread.sleep(50); } } catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { ThreadDemo T1 = new ThreadDemo( "Thread-1"); T1.start(); ThreadDemo T2 = new ThreadDemo( "Thread-2"); T2.start(); } }
输出
Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, 4 Running Thread-2 Thread: Thread-2, 4 Thread: Thread-1, 3 Thread: Thread-2, 3 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-1, 1 Thread: Thread-2, 1 Thread Thread-1 exiting. Thread Thread-2 exiting.
线程方法
以下是Thread类中可用的一些重要方法列表。
序号 | 方法及描述 |
---|---|
1 | public void start() 在单独的执行路径中启动线程,然后在此Thread对象上调用run()方法。 |
2 | public void run() 如果此Thread对象是使用单独的Runnable目标实例化的,则在此Runnable对象上调用run()方法。 |
3 | public final void setName(String name) 更改Thread对象的名称。还有一个getName()方法用于检索名称。 |
4 | public final void setPriority(int priority) 设置此Thread对象的优先级。可能的值介于1到10之间。 |
5 | public final void setDaemon(boolean on) 值为true表示此线程为守护线程。 |
6 | public final void join(long millisec) 当前线程在此第二个线程上调用此方法,导致当前线程阻塞,直到第二个线程终止或指定的毫秒数过去。 |
7 | public void interrupt() 中断此线程,使其继续执行(如果由于任何原因而被阻塞)。 |
8 | public final boolean isAlive() 如果线程处于活动状态,则返回true,即线程启动后但在运行完成之前。 |
之前的方法是在特定的Thread对象上调用的。Thread类中的以下方法是静态的。调用其中一个静态方法会在当前正在运行的线程上执行操作。
序号 | 方法及描述 |
---|---|
1 | public static void yield() 导致当前正在运行的线程让出给任何其他具有相同优先级且正在等待调度的线程。 |
2 | public static void sleep(long millisec) 导致当前正在运行的线程至少阻塞指定毫秒数。 |
3 | public static boolean holdsLock(Object x) 如果当前线程持有给定Object上的锁,则返回true。 |
4 | public static Thread currentThread() 返回对当前正在运行的线程的引用,该线程是调用此方法的线程。 |
5 | public static void dumpStack() 打印当前正在运行的线程的堆栈跟踪,这在调试多线程应用程序时很有用。 |
示例
以下ThreadClassDemo程序演示了Thread类的一些方法。考虑一个实现Runnable的DisplayMessage类:
// File Name : DisplayMessage.java // Create a thread to implement Runnable public class DisplayMessage implements Runnable { private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); } } }
以下是另一个扩展Thread类的类:
// File Name : GuessANumber.java // Create a thread to extentd Thread public class GuessANumber extends Thread { private int number; public GuessANumber(int number) { this.number = number; } public void run() { int counter = 0; int guess = 0; do { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; } while(guess != number); System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**"); } }
以下是主程序,它使用了上面定义的类:
// File Name : ThreadClassDemo.java public class ThreadClassDemo { public static void main(String [] args) { Runnable hello = new DisplayMessage("Hello"); Thread thread1 = new Thread(hello); thread1.setDaemon(true); thread1.setName("hello"); System.out.println("Starting hello thread..."); thread1.start(); Runnable bye = new DisplayMessage("Goodbye"); Thread thread2 = new Thread(bye); thread2.setPriority(Thread.MIN_PRIORITY); thread2.setDaemon(true); System.out.println("Starting goodbye thread..."); thread2.start(); System.out.println("Starting thread3..."); Thread thread3 = new GuessANumber(27); thread3.start(); try { thread3.join(); } catch (InterruptedException e) { System.out.println("Thread interrupted."); } System.out.println("Starting thread4..."); Thread thread4 = new GuessANumber(75); thread4.start(); System.out.println("main() is ending..."); } } class DisplayMessage implements Runnable { private String message; public DisplayMessage(String message) { this.message = message; } public void run() { while(true) { System.out.println(message); } } } class GuessANumber extends Thread { private int number; public GuessANumber(int number) { this.number = number; } public void run() { int counter = 0; int guess = 0; do { guess = (int) (Math.random() * 100 + 1); System.out.println(this.getName() + " guesses " + guess); counter++; } while(guess != number); System.out.println("** Correct!" + this.getName() + "in" + counter + "guesses.**"); } }
输出
Starting hello thread... Starting goodbye thread... Hello Hello Hello Hello Hello Hello Goodbye Goodbye Goodbye Goodbye Goodbye .......
主要的Java多线程概念
在Java中进行多线程编程时,您需要掌握以下概念: