Java多线程知识点
Java多线程是并发编程的一种形式,它允许在一个程序中同时运行多个线程。每个线程都是程序执行流,拥有自己的堆栈和程序计数器,但共享程序的其他部分(如内存和静态变量)。
一、线程与进程
- 进程:程序运行资源分配的最小单位。进程有自己的独立地址空间,系统为它分配地址空间并建立数据表来维护代码段、堆栈段和数据段。
- 线程:CPU调度的最小单位,必须依赖进程而存在。线程共享进程中的资源,使用相同的地址空间,因此CPU切换线程的开销比进程小。
二、线程的实现方式
1. 继承Thread类
通过继承Thread类并重写其run()方法来实现多线程。但Java只支持单继承,因此这种方式有一定的局限性。
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
}
}
### 2. 实现Runnable接口
实现Runnable接口并重写其run()方法,然后将Runnable对象传递给Thread对象。这种方式更为灵活,因为可以实现多个接口。
```java
class MyRunnable implements Runnable {
@Override
public void run() { // 线程执行的代码
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
3. 实现Callable接口
与Runnable接口类似,但Callable接口允许线程任务有返回值,并且可以抛出异常。配合Future获取线程的执行结果。
import java.util.concurrent.*;
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
// 线程执行的代码,返回整数结果
return 1;
}
}
Callable<Integer> callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
Thread thread = new Thread(futureTask);
thread.start();
Integer result = futureTask.get(); // 获取线程执行结果
4. 线程池
线程池提供了一种管理和复用线程的机制,减少了线程的创建和销毁开销,提高了程序的性能。Java提供了多种线程池实现,如FixedThreadPool、CachedThreadPool和ScheduledThreadPool等。
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(new RunnableTask()); // 提交任务给线程池
executorService.shutdown(); // 关闭线程池
三、线程的生命周期
Java中的线程具有多种状态,包括新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)。线程在其生命周期中会在这些状态之间转换。
- 新建状态:线程对象被创建,但尚未调用start()方法。
- 就绪状态:线程调用start()方法后进入就绪状态,等待CPU调度。
- 运行状态:线程获得CPU,开始执行run()方法
- 阻塞状态:线程因为某些原因(如sleep、wait、join等)暂时停止运行。
- 死亡状态:线程的run()方法执行完毕或被强制终止。
四、线程同步与线程安全
由于多个线程共享程序的资源,因此需要对这些资源进行同步以防止数据不一致或冲突。Java提供了多种同步机制来确保线程安全。
1. synchronized关键字
可以使用synchronized关键字来修饰方法或代码块,从而实现线程同步。
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
2. Lock接口
Lock接口提供了比synchronized更灵活的同步机制,支持显式加锁和解锁。常用的实现类有ReentrantLock。
import java.util.concurrent.locks.ReentrantLock;
class Counter private int count = 0;
private final ReentrantLock lock = new ReentrantLock();
public void increment() {
lock.lock();
try count++;
} finally {
lock.unlock();
}
}
public int getCount() {
lock.lock();
try {
return count;
} finally {
lock.unlock();
}
}
}
五、其他重要概念
- 守护线程:守护线程是一种特殊的线程,当主线程结束时,守护线程也会自动结束。可以通过setDaemon(true)方法将线程设置为守护线程。
- ThreadLocal:ThreadLocal为变量在每个线程中都创建了一个副本,使得每个线程都可以访问自己内部的副本变量,从而实现线程隔离。
- CAS操作:CAS(Compare And Swap)是一种原子操作,用于实现无锁算法。它可以有效地提升并发的效率,但同时也会引入ABA问题。
评论一下吧
取消回复