Java 多线程编程:从基础到实战!
全文目录:
- 开篇语
- **前言**
- 1. **线程基础概念**
- 1.1 **什么是线程?**
- 1.2 **线程的生命周期**
- 2. **线程的创建与启动**
- 2.1 **继承 `Thread` 类**
- 2.2 **实现 `Runnable` 接口**
- 3. **线程的同步**
- 3.1 **使用 `synchronized` 关键字**
- 示例:使用 `synchronized` 修饰方法
- 3.2 **使用 `ReentrantLock`**
- 4. **线程的通信**
- 4.1 **使用 `wait()` 和 `notify()`**
- 5. **线程池**
- 5.1 **使用 `ExecutorService` 创建线程池**
- 6. **总结**
- 文末
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。
小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!
前言
多线程编程是 Java 中的一个核心概念,它允许多个线程同时执行任务,从而提高程序的效率和响应性。在现代应用程序中,多线程编程无处不在,尤其是在处理高并发任务时。今天,我们将从基础到实战深入讲解 Java 的多线程编程,帮助你更好地理解和应用它。
1. 线程基础概念
1.1 什么是线程?
线程是操作系统能够进行调度的最小单位。每个 Java 程序在启动时,都会自动创建一个主线程。通过多线程编程,多个线程可以同时执行不同的任务。
线程是属于进程的,每个线程都有自己的执行路径。多线程可以并发地执行任务,提高程序的效率,尤其是在 CPU 密集型和 I/O 密集型任务中。
1.2 线程的生命周期
线程的生命周期主要包括以下几个阶段:
- 新建(New):线程对象创建后,还未调用
start()
方法时,处于新建状态。 - 就绪(Runnable):线程调用
start()
方法后,处于就绪状态。操作系统会将就绪的线程分配 CPU 时间片,开始执行任务。 - 运行(Running):线程获得 CPU 时间片后,进入运行状态,开始执行任务。
- 阻塞(Blocked):线程在等待某些资源(如 I/O、锁等)时,会进入阻塞状态。
- 死亡(Dead):线程执行完任务后进入死亡状态。
2. 线程的创建与启动
在 Java 中,创建和启动线程的方式有两种:继承 Thread
类和实现 Runnable
接口。
2.1 继承 Thread
类
通过继承 Thread
类并重写 run()
方法来实现线程。然后通过调用 start()
方法来启动线程。
class MyThread extends Thread {@Overridepublic void run() {System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");}public static void main(String[] args) {MyThread thread1 = new MyThread();MyThread thread2 = new MyThread();thread1.start(); // 启动线程thread2.start();}
}
2.2 实现 Runnable
接口
通过实现 Runnable
接口,并将 Runnable
实现类传递给 Thread
构造函数,再调用 start()
方法来启动线程。这个方法的优势是支持多继承。
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");}public static void main(String[] args) {MyRunnable task = new MyRunnable();Thread thread1 = new Thread(task);Thread thread2 = new Thread(task);thread1.start(); // 启动线程thread2.start();}
}
3. 线程的同步
多线程编程中,一个常见的问题是多个线程访问共享资源时,可能会导致数据不一致的问题。为了解决这个问题,Java 提供了多种同步机制。
3.1 使用 synchronized
关键字
synchronized
是 Java 中用于控制对共享资源的访问的关键字。它可以确保同一时刻只有一个线程能够执行被 synchronized
修饰的代码块。
示例:使用 synchronized
修饰方法
class Counter {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}public class SynchronizedExample {public static void main(String[] args) {Counter counter = new Counter();// 创建多个线程并执行任务Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("最终计数值:" + counter.getCount());}
}
3.2 使用 ReentrantLock
ReentrantLock
是一种更灵活的锁机制,它比 synchronized
更加可控,支持尝试锁、定时锁等高级功能。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class Counter {private int count = 0;private Lock lock = new ReentrantLock();public void increment() {lock.lock(); // 获取锁try {count++;} finally {lock.unlock(); // 释放锁}}public int getCount() {return count;}
}public class LockExample {public static void main(String[] args) {Counter counter = new Counter();// 创建多个线程并执行任务Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});thread1.start();thread2.start();try {thread1.join();thread2.join();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("最终计数值:" + counter.getCount());}
}
4. 线程的通信
在某些情况下,多个线程需要相互协作,完成任务。Java 提供了 wait()
、notify()
和 notifyAll()
方法来进行线程间的通信。
4.1 使用 wait()
和 notify()
wait()
方法使当前线程进入等待状态,直到其他线程调用 notify()
或 notifyAll()
方法时,当前线程才会被唤醒。
class SharedResource {private boolean flag = false;public synchronized void produce() throws InterruptedException {while (flag) {wait(); // 如果已经生产了,就等待}System.out.println("生产者生产了一个产品");flag = true;notify(); // 唤醒消费者}public synchronized void consume() throws InterruptedException {while (!flag) {wait(); // 如果没有产品,就等待}System.out.println("消费者消费了一个产品");flag = false;notify(); // 唤醒生产者}
}public class WaitNotifyExample {public static void main(String[] args) {SharedResource resource = new SharedResource();// 生产者线程Thread producer = new Thread(() -> {try {while (true) {resource.produce();Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}});// 消费者线程Thread consumer = new Thread(() -> {try {while (true) {resource.consume();Thread.sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}});producer.start();consumer.start();}
}
5. 线程池
线程池是为了减少线程创建和销毁的开销,提升程序效率而设计的。Java 提供了 ExecutorService
接口和它的实现类 ThreadPoolExecutor
来管理线程池。
5.1 使用 ExecutorService
创建线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ExecutorServiceExample {public static void main(String[] args) {// 创建一个固定大小的线程池ExecutorService executor = Executors.newFixedThreadPool(3);// 提交任务给线程池for (int i = 0; i < 5; i++) {executor.submit(() -> {System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");});}// 关闭线程池executor.shutdown();}
}
6. 总结
多线程编程是 Java 编程中的一个重要部分,它能够提升程序的性能和响应速度。通过学习 Java 中的线程创建、同步、通信和线程池等内容,你可以更好地理解如何在 Java 中实现并发处理。
今天,我们从 Java 线程的基础概念到高级特性进行了详细的讲解,并通过实例帮助大家更好地理解多线程编程的核心要点。希望这篇文章能够帮助你更好地掌握 Java 多线程编程!
… …
文末
好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。
… …
学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!
wished for you successed !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!