Java 多线程编程:从基础到实战!
开篇语
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区: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 {
@Override
public 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 {
@Override
public 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 !!!
⭐️若喜欢我,就请关注我叭。
⭐️若对您有用,就请点赞叭。
⭐️若有疑问,就请评论留言告诉我叭。
版权声明:本文由作者原创,转载请注明出处,谢谢支持!
- 点赞
- 收藏
- 关注作者
评论(0)