废话不多说直接开始
线程与进程
进程是系统资源分配、调度基本单位,拥有独立内存空间,像电脑上运行的浏览器、音乐播放器,各自独立运行互不干扰。线程是进程内执行单元,共享进程资源,一个进程可有多个线程,它们好比工厂里不同分工工人,协作完成进程“生产目标”。
在 Java 中,创建线程有两种常见方式:
1. 继承 Thread 类:定义子类重写 run() 方法, run() 里写线程执行逻辑,用 start() 方法启动线程。代码示例:
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行");
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
2. 实现 Runnable 接口:实现 run() 方法,再借助 Thread 类包装启动。这种方式避免单继承局限,利于代码复用,代码示例:
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable 线程运行");
}
}
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
并发编程里的安全隐患及锁机制
多线程环境好似热闹集市,大家共享资源时极易“撞车”。比如多个线程同时读写一个文件,数据立马乱套。这背后涉及原子性、可见性、有序性难题。
原子性意味着操作不可拆分,要么完整执行,要么纹丝不动。Java 提供 AtomicInteger 这类原子类,其方法能确保原子操作,守护操作完整性;可见性要求线程修改共享变量后,其他线程能即刻察觉变化,用 volatile 关键字修饰变量,就是让变量修改“尽人皆知”;有序性旨在防止指令重排序扰乱程序逻辑, synchronized 关键字搭配锁机制,牢牢维系指令原有顺序。
synchronized 堪称守护共享资源的“大闸”,修饰方法或代码块后,同一时间只允许一个线程进入资源,独占资源访问权。
例子:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
线程间的通信与协作
线程间时常需要协作,生产者 - 消费者模式便是经典范例。生产者负责产出数据,消费者专职消耗数据,中间仓库作为共享资源,库存满时生产者歇着,库存空时消费者等待。Java 里, Object 类的 wait() 、 notify() 、 notifyAll() 方法就是调度员,搭配 synchronized 管控线程状态,实现精准唤醒与等待。