Java多线程详解
创始人
2025-05-31 21:03:02
0

线程是什么?


线程是计算机中一种轻量级的进程,它是程序执行的基本单位,可以看做是进程中的一个小部分。

线程与进程不同,进程是操作系统进行资源分配和调度的基本单位,每个进程都有自己的独立内存空间和系统资源,进程之间相互独立。而线程是进程中的实际执行单位,一个进程中可以包含多个线程,这些线程共享同一份内存空间和资源。

一个线程拥有自己的ID、PC(程序计数器)、寄存器集合和栈区域等线程上下文(Thread Context),每个线程都有自己的状态,包括初始态、就绪态、运行态、阻塞态和死亡态。

在Java中,线程是由Thread类来实现的,也可以通过实现Runnable接口来创建线程,然后通过调用start()方法来启动线程的执行。线程执行完后会进入终止状态,不能再次启动执行。

线程的特点包括:

  • 线程是轻量级的执行单元,创建和销毁线程的开销很小。

  • 线程可以并发执行,可以利用多核CPU提高程序的执行效率。

  • 线程之间可以共享同一份数据空间,便于信息的共享和通信。

  • 线程的执行顺序和优先级可以通过调度算法来控制。

由于线程之间共享同一份内存空间和资源,因此在多线程编程中需要注意线程安全问题,如对共享变量的并发访问可能带来的数据竞争和死锁等问题。

线程的使用可以大大提高程序性能和执行效率,可以将任务并发执行从而缩短响应时间和提高效率,但也要注意避免过多创建线程带来的负面影响。同时,需要合理地利用锁、原子操作等技术来保证线程安全和正确性。

Java多线程基础


线程基础知识

  • 线程的概念:线程是操作系统能够进行运算调度的最小单位,它被包含在进程中,是进程中的实际运作单位。

  • 线程的状态:线程的状态包括新建状态、就绪状态、运行状态、阻塞状态和死亡状态。

  • 线程的创建:Java提供了三种方式来创建线程,分别是继承Thread类、实现Runnable接口和使用Executors框架。其中,实现Runnable接口是比较推荐的方式,因为Java只支持单继承,而且实现Runnable的方式更符合“高内聚低耦合”的设计思想。

  • 线程的同步:线程同步是指多个线程访问共享资源时的同步问题,Java提供了synchronized关键字和Lock接口来解决这一问题。

  • 线程的通信:线程通信是指多个线程之间的信息传递和协作,Java提供了wait()、notify()和notifyAll()等方法实现线程通信。

线程安全

线程安全是指多线程环境下程序始终能够正确地执行,不会出现数据不一致、死锁等问题。Java线程安全问题的产生通常涉及到以下几个方面:

  • 共享数据:多个线程访问同一块数据时容易出现线程安全问题。

  • 不可变数据:多个线程访问同一块数据时,如果数据是不可变的,则不会存在线程安全问题。

  • 线程操作:对于同一块数据,在同一时刻只能由一个线程进行操作,不能同时由多个线程操作。

Java提供了synchronized关键字用于解决线程同步问题,synchronized关键字可以保证同一时刻只有一个线程执行该代码块或方法。除此之外,Java还提供了Atomic包、Lock接口等方式来实现线程同步。

线程池

线程池是指在程序启动时预先创建若干个线程,并将这些线程存储在一个线程集合中,需要时直接从中获取线程来执行任务,执行完毕后再放回线程集合中。线程池的好处是可以避免频繁创建与销毁线程的开销,提高程序的性能。Java提供了ThreadPoolExecutor类来实现线程池,开发者可以根据自己的需求配置线程池的大小、线程存活时间、队列类型等参数。

Java多线程实现


继承Thread类方式

class MyThread extends Thread {@Overridepublic void run() {// 线程执行的业务逻辑}
}public class Main {public static void main(String[] args) {Thread thread = new MyThread();thread.start();}
}

实现Runnable接口方式

class MyRunnable implements Runnable {@Overridepublic void run() {// 线程执行的业务逻辑}
}public class Main {public static void main(String[] args) {Runnable runnable = new MyRunnable();Thread thread = new Thread(runnable);thread.start();}
}

使用Lambda表达式方式

public class Main {public static void main(String[] args) {Thread thread = new Thread(() -> {// 线程执行的业务逻辑});thread.start();}
}

线程同步

synchronized关键字

class MyObject {private int count;public synchronized void increase() {count++;}
}public class Main {public static void main(String[] args) {MyObject myObject = new MyObject();for (int i = 0; i < 10; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {myObject.increase();}}).start();}// 等待所有子线程执行完毕while (Thread.activeCount() > 2) {Thread.yield();}System.out.println(myObject.getCount());}
}

Lock接口

class MyObject {private int count;private Lock lock = new ReentrantLock();public void increase() {try {lock.lock();count++;} finally {lock.unlock();}}
}public class Main {public static void main(String[] args) {MyObject myObject = new MyObject();for (int i = 0; i < 10; i++) {new Thread(() -> {for (int j = 0; j < 1000; j++) {myObject.increase();}}).start();}// 等待所有子线程执行完毕while (Thread.activeCount() > 2) {Thread.yield();}System.out.println(myObject.getCount());}
}

线程通信

wait()和notify()

class MyObject {private int count;public synchronized void produce() throws InterruptedException {while (count >= 10) {wait();}count++;System.out.println(Thread.currentThread().getName() + " produce " + count);notifyAll();}public synchronized void consume() throws InterruptedException {while (count <= 0) {wait();}count--;System.out.println(Thread.currentThread().getName() + " consume " + count);notifyAll();}
}public class Main {public static void main(String[] args) {MyObject myObject = new MyObject();new Thread(() -> {for (int i = 0; i < 10; i++) {try {myObject.produce();} catch (InterruptedException e) {e.printStackTrace();}}}, "producer").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {myObject.consume();} catch (InterruptedException e) {e.printStackTrace();}}}, "consumer").start();}
}

Condition接口

class MyObject {private int count;private Lock lock = new ReentrantLock();private Condition producerCondition = lock.newCondition();private Condition consumerCondition = lock.newCondition();public void produce() throws InterruptedException {try {lock.lock();while (count >= 10) {producerCondition.await();}count++;System.out.println(Thread.currentThread().getName() + " produce " + count);consumerCondition.signalAll();} finally {lock.unlock();}}public void consume() throws InterruptedException {try {lock.lock();while (count <= 0) {consumerCondition.await();}count--;System.out.println(Thread.currentThread().getName() + " consume " + count);producerCondition.signalAll();} finally {lock.unlock();}}
}public class Main {public static void main(String[] args) {MyObject myObject = new MyObject();new Thread(() -> {for (int i = 0; i < 10; i++) {try {myObject.produce();} catch (InterruptedException e) {e.printStackTrace();}}}, "producer").start();new Thread(() -> {for (int i = 0; i < 10; i++) {try {myObject.consume();} catch (InterruptedException e) {e.printStackTrace();}}}, "consumer").start();}
}

线程池

// 创建一个具有固定线程数(5个)的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);// 向线程池提交一个任务(Runnable或Callable)
executor.submit(new Runnable() {@Overridepublic void run() {// 线程具体执行的操作}
});// 关闭线程池
executor.shutdown();

上面的代码中,通过调用Executors.newFixedThreadPool()方法创建一个具有固定线程数的线程池,然后通过executor.submit()方法向线程池提交一个任务,最后通过executor.shutdown()方法关闭线程池。

除了newFixedThreadPool()方法以外,还有其他常见类型的线程池,如:

  • newCachedThreadPool():一个可以动态调整线程数量的线程池,不限制线程数量,会根据需要自动创建和销毁线程,适用于处理大量短时间的任务。

  • newSingleThreadExecutor():一个只有一个工作线程的线程池,适用于需要保证任务按照指定顺序(如FIFO、LIFO、优先级)执行的场合。

线程池的做法可以避免频繁创建和销毁线程带来的性能开销,提高了线程的复用和管理效率,同时也可以避免线程数量过多导致资源耗尽的风险。根据实际的业务需求,可以选择合适的线程池类型和线程数量配置。

相关内容

热门资讯

原创 赵... 大家追剧的时候最喜欢看什么呢?小妹儿最喜欢看的就是CP们甜甜蜜蜜的亲亲抱抱,而现如今的内娱,更是把C...
晶澳科技港股递表失效逾两月 超... 《金证研》南方资本中心 望山*DL/作者 西洲 映蔚/风控在证监会出具的境外发行上市备案补充材料要求...
16倍大牛股陷资本迷局,“AI... 本文来源:时代周报 作者:宋逸霆1月16日晚间,天普股份(605255.SH)发布关于对上交所问询函...
美股大型科技股集体上涨 1月16日,美股三大指数集体高开,标普500指数涨0.22%,道指涨0.18%,纳指涨0.44%。 ...
以为海外收入税务局查不到?这个... 2026年初这波针对境外收入的合规自查行动,力度之大、追溯之深,确实让不少人心头一紧。最近关于境外收...
净利300亿!中信证券走出寒冬... 出品|达摩财经首份2025年券商年度业绩快报出炉。1月14日,中信证券(600030.SH)发布业绩...
一年卖出250亿双,浙江小镇,... 你知道这些袜子大多都来自哪里吗?不少人或许会认为是义乌,实际上,国内最大的袜子产业带,是同处浙江的诸...
碳酸锂价格“过山车”!锂电企业... 本文来源:时代周报 作者:周松清尽管碳酸锂期货价格近日出现回调,但今年以来涨幅仍较大。1月16日,碳...
杭萧钢构遭上交所警示 股价连续... 中经记者 方超 石英婧 上海报道在商业航天热度不减背景下,杭萧钢构股份有限公司(600477.SH,...
中欧电动汽车案“软着陆”具有积... 文/对外经济贸易大学中国WTO研究院 屠新泉1月12日,中欧双方分别宣布就欧盟对华电动汽车反补贴案达...