一文搞懂Java多线程基础(锁机制、线程通信、线程池)
发布日期:2021-05-08 16:15:58 浏览次数:17 分类:精选文章

本文共 3951 字,大约阅读时间需要 13 分钟。

Java多线程入门指南

1. 理解进程与线程

在计算机操作系统中,进程和线程是资源管理的核心概念。进程被认为是资源分配和调度的最小单位,而线程则是程序执行的最小单位。每个进程可以包含一个或多个线程,线程之间共享同一进程的内存空间。

进程特征

  • 动态性:进程是临时的,随着任务需求动态创建和消亡。
  • 并发性:进程可以与其他进程并行执行。
  • 独立性:进程是资源分配的基本单位。
  • 结构性:由程序、数据和控制块组成。

线程特性

  • 轻量级:线程上下文切换比进程快,适合处理I/O密集型任务。
  • 共享内存:同一进程内的线程共享程序内存空间。
  • 并发执行:线程之间可以并发执行,提升系统效率。

2. Java中线程的创建方式

在Java中,创建线程主要通过以下方式:

1. 继承Thread类

  • 步骤
  • 创建自定义Thread子类,重写run()方法。
  • 创建线程实例。
  • 调用start()方法启动线程。

示例代码:

public class MyThread extends Thread {
@Override
public void run() {
// 线程执行逻辑
}
}
MyThread mt = new MyThread();
mt.start();

2. 实现Runnable接口

  • 步骤
  • 创建Runnable接口实现类,重写run()方法。
  • 创建Thread对象,将Runnable实例作为参数传递。
  • 调用start()方法启动线程。

示例代码:

public class MyThread implements Runnable {
@Override
public void run() {
// 线程执行逻辑
}
}
MyThread mt = new MyThread();
new Thread(mt).start();

3. 匿名内部类

  • 方式
  • 在方法内定义匿名内部类,继承Thread或实现Runnable。
  • 重写run()方法。
  • 创建Thread对象并启动。

示例代码:

public static void main(String[] args) {
new Thread() {
@Override
public void run() {
// 线程执行逻辑
}
}.start();
}

4. Runnable匿名类

  • 方式
  • 创建Runnable匿名类,重写run()方法。
  • 创建Thread对象并启动。

示例代码:

public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
// 线程执行逻辑
}
};
new Thread(r).start();
}

3. 线程安全问题

多线程环境下,共享资源可能导致并发问题。解决方法是使用同步机制。

1. synchronized锁

  • 作用:防止多个线程同时访问共享资源。
  • 使用方式:修饰方法或代码块,确保同步访问。

示例代码:

synchronized (this) {
// 共享资源访问逻辑
}

2. ReentrantLock锁

  • 特点:支持重入锁,手动加锁和解锁。
  • 使用方式:调用lock()unlock()方法,确保锁的使用和释放。

示例代码:

ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 共享资源访问逻辑
} finally {
lock.unlock();
}

3. lock和ReentrantLock对比

  • synchronized:自动加锁和解锁,适合简单场景。
  • ReentrantLock:手动控制锁,适合复杂需求,支持公平锁机制。

4. 线程通信

线程通信是多线程程序中常见的操作,常用wait()notify()notifyAll()方法。

1. wait和notify

  • 作用:wait方法让线程等待特定对象的通知,notify方法唤醒正在等待的线程。

示例代码:

public class MyThread extends Thread {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("线程1执行");
notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

2. notifyAll

  • 作用:唤醒等待队列中所有线程。

示例代码:

public class MyThread extends Thread {
public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
t1.start();
t2.start();
try {
Thread.sleep(1000);
t1.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("线程" + getId() + "执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

5. 线程池

线程池是什么?

线程池是一个容纳多个线程的容器,线程可以反复使用,避免频繁创建线程。

线程池的好处

  • 降低资源消耗:减少线程创建和销毁次数。
  • 提高响应速度:任务立即执行。
  • 提高可管理性:根据需求调整线程数。

线程池的实现

import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 10, TimeUnit.SECONDS);
executor.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
System.out.println("新线程执行");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
TimeUnit.SECONDS.sleep(2);
executor.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

6. 总结

通过以上内容,我们全面了解了Java中的多线程编程,包括线程的创建、线程安全问题、线程通信以及线程池的使用。掌握这些知识点是写高效、可靠的多线程程序的基础。

上一篇:Java之 反射
下一篇:Java 字节流读取read ()方法返回int 而不是byte 的原因

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月16日 00时56分43秒