第3课_Java多线程与并发
热度🔥:37 免费课程
授课语音
Java多线程基础与并发编程技巧
在多核CPU和大规模并发环境中,Java的多线程编程是提高应用性能的关键。理解并掌握多线程的基本原理和编程技巧,对于开发高效且稳定的Java应用至关重要。本课程将详细介绍Java多线程的基础知识和常见的并发编程技巧,包括线程的创建、线程池、同步、并发集合等内容。
1. Java多线程基础
1.1 线程的概念
线程是计算机程序中执行的最小单位。一个程序中可以同时存在多个线程,它们共享程序的资源。线程之间的并发执行可以大大提高计算机的工作效率。
1.2 创建线程的方式
在Java中,创建线程有两种主要的方式:
- 继承Thread类:通过继承Thread类并重写其
run()
方法来创建线程。 - 实现Runnable接口:通过实现
Runnable
接口并重写其run()
方法来创建线程。
1.2.1 继承Thread类创建线程
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行中...");
}
}
public class ThreadDemo {
public static void main(String[] args) {
// 创建线程并启动
MyThread thread = new MyThread();
thread.start();
}
}
1.2.2 实现Runnable接口创建线程
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程执行中...");
}
}
public class ThreadDemo {
public static void main(String[] args) {
// 创建Runnable对象
MyRunnable runnable = new MyRunnable();
// 创建线程并启动
Thread thread = new Thread(runnable);
thread.start();
}
}
1.3 线程的生命周期
线程的生命周期包含以下几个状态:
- 新建状态(New):线程被创建但尚未启动。
- 就绪状态(Runnable):线程已准备好执行,但调度器尚未分配 CPU 时间片给该线程。
- 运行状态(Running):线程获得 CPU 时间片并执行。
- 阻塞状态(Blocked):线程因等待资源而进入阻塞状态。
- 终止状态(Terminated):线程执行完毕或因异常终止。
2. Java并发编程技巧
2.1 线程同步
在多线程环境下,多个线程可能会同时访问共享资源,造成数据不一致的情况。为了解决这个问题,Java提供了线程同步机制,常见的方式包括:
- synchronized关键字:用于修饰方法或代码块,确保同一时刻只有一个线程能够执行。
2.1.1 使用synchronized
修饰实例方法
class Counter {
private int count = 0;
// 使用synchronized修饰实例方法,保证线程安全
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
public class SyncExample {
public static void main(String[] args) {
Counter counter = new Counter();
// 创建多个线程同时执行增值操作
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
t1.start();
t2.start();
}
}
2.1.2 使用synchronized
修饰代码块
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public int getCount() {
return count;
}
}
2.2 线程池
线程池是用于管理线程的容器,它能有效地减少线程的创建和销毁带来的性能开销。Java通过ExecutorService
接口和其实现类提供了线程池功能。
2.2.1 使用线程池执行任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
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();
}
}
2.3 并发集合
在多线程环境下,使用普通的集合类(如ArrayList
、HashMap
)可能会出现线程安全问题。Java提供了java.util.concurrent
包中的并发集合类,它们本身是线程安全的,常见的并发集合有:
ConcurrentHashMap
CopyOnWriteArrayList
BlockingQueue
2.3.1 使用ConcurrentHashMap
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentMapExample {
public static void main(String[] args) {
// 创建并发HashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 在多个线程中操作并发Map
for (int i = 0; i < 10; i++) {
final int j = i;
new Thread(() -> map.put("key" + j, j)).start();
}
// 打印结果
System.out.println(map);
}
}
3. 并发编程的高级技巧
3.1 线程的通信
Java提供了多种机制来实现线程间的通信:
- wait() 和 notify():这些方法用于线程间的协调和通知。
- CountDownLatch:允许一个或多个线程等待直到在其他线程中执行的一组操作完成。
- CyclicBarrier:使一组线程互相等待,直到所有线程都到达某个公共屏障点。
3.1.1 使用wait()
和notify()
进行线程通信
class MyQueue {
private int count = 0;
public synchronized void produce() throws InterruptedException {
while (count >= 1) {
wait(); // 如果队列已满,等待
}
count++;
System.out.println("生产者生产了一个产品,当前数量:" + count);
notify(); // 唤醒消费者线程
}
public synchronized void consume() throws InterruptedException {
while (count <= 0) {
wait(); // 如果队列为空,等待
}
count--;
System.out.println("消费者消费了一个产品,当前数量:" + count);
notify(); // 唤醒生产者线程
}
}
public class WaitNotifyExample {
public static void main(String[] args) {
MyQueue queue = new MyQueue();
// 创建生产者线程
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
queue.produce();
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// 创建消费者线程
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 5; i++) {
queue.consume();
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
}
}
4. 总结
Java多线程编程虽然强大,但也容易出错。掌握线程的基础知识、同步技巧、线程池的使用及并发集合的应用,能够帮助开发者编写高效、稳定的并发程序。通过灵活使用线程通信和高级并发工具,可以进一步提升程序的性能和可靠性。