在 Java 中,多线程编程是一项重要的技能,尤其是在处理并发任务、提高程序性能和响应性方面。以下是关于 Java 多线程模型和常用方法的介绍:
线程(Thread): 是程序执行的最小单元,Java 中通过继承 Thread 类或实现 Runnable 接口来创建线程。
进程(Process): 是程序的一次执行,每个 Java 程序都至少有一个进程。
新建(New): 线程被创建但尚未启动。
就绪(Runnable): 线程等待执行,具备执行条件。
运行(Running): 线程正在执行。
阻塞(Blocked): 线程等待某个条件的解除。
死亡(Dead): 线程执行完毕或被终止。
Java 的线程调度由 JVM 的线程调度器负责。
yield() 方法可使当前线程让步给其他线程。
sleep() 方法可使线程休眠一段时间。
a. 继承 Thread 类:
class MyThread extends Thread {
public void run() {
// 线程执行的代码
}
}
// 创建并启动线程
MyThread myThread = new MyThread();
myThread.start();
b. 实现 Runnable 接口:
class MyRunnable implements Runnable {
public void run() {
// 线程执行的代码
}
}
// 创建并启动线程
Thread thread = new Thread(new MyRunnable());
thread.start();
用于保护代码块或方法,防止多个线程同时执行该代码块或方法。
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
}
显示锁,提供了与 synchronized 类似的同步功能。
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
a. wait() 和 notify():
wait() 使线程等待,notify() 唤醒等待的线程。
class SharedResource {
boolean flag = false;
synchronized void printNumber() {
while (!flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Print odd/even number");
flag = !flag;
notify();
}
synchronized void printAlphabet() {
while (flag) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Print alphabet");
flag = !flag;
notify();
}
}
a. Executor 框架:
ExecutorService 提供了一种管理和控制线程的方式。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
// 线程执行的任务
});
}
executorService.shutdown();
}
}
ConcurrentHashMap 是 HashMap 的线程安全版本,适用于多线程环境,提供了较好的并发性能。与传统的同步 HashMap 不同,ConcurrentHashMap 使用分段锁机制,将数据分成多个段,每个段上都有独立的锁,使得多线程可以并发地读取和写入不同的段,提高了并发性。
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentHashMapExample {
public static void main(String[] args) {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("one", 1);
map.put("two", 2);
// 线程安全的读取
int value = map.get("one");
System.out.println("Value: " + value);
// 线程安全的写入
map.put("three", 3);
}
}
CountDownLatch 是一个同步辅助类,用于表示一个或多个线程等待一组事件的发生。它通过一个计数器来实现,初始值设定为需要等待的事件数量,每当一个事件发生时,计数器减一。当计数器为零时,所有等待的线程被唤醒。
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> {
// 执行任务
System.out.println("Task completed");
latch.countDown(); // 事件发生,计数器减一
};
// 启动多个线程执行任务
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
// 等待所有任务完成
latch.await();
System.out.println("All tasks completed");
}
}
Semaphore 是一个计数信号量,用于控制同时访问的线程数。它维护了一定数量的许可证,线程在访问临界区之前需要先获得许可证,执行完毕后释放许可证。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 允许两个线程同时访问
Runnable task = () -> {
try {
semaphore.acquire(); // 获取许可证
// 执行任务
System.out.println("Task completed");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release(); // 释放许可证
}
};
// 启动多个线程执行任务
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
以上是 Java 多线程模型和常用方法的简要介绍,深入理解这些概念和方法可以帮助你更好地设计和实现多线程应用,提高系统的并发性能。
针对多线程具体的方法放在这,持续更新中
java多线程方法整理
基于JDK1.8多线程常用解决方式-CyclicBarrier(循环栅栏)
基于JDK1.8多线程常用解决方式-CountDownLatch(倒计数器)