Java中的多线程编程:从基础到实践

简介: 【10月更文挑战第13天】 Java作为一门跨平台的编程语言,其强大的多线程能力一直是其核心优势之一。本文将从最基础的概念讲起,逐步深入探讨Java多线程的实现方式及其应用场景,通过实例讲解帮助读者更好地理解和应用这一技术。

Java语言自从其诞生之初就支持多线程,这使得它在处理并发任务时具备得天独厚的优势。多线程不仅能够有效提升程序的执行效率,还能改善用户体验。下面我们将分几个部分来详细讲解Java中的多线程编程。

一、基本概念

  1. 进程与线程

    • 进程(Process)是操作系统分配资源的最小单位,每个进程都有自己独立的内存空间。
    • 线程(Thread)是进程中实际运行的单元,一个进程可以包含多个线程,这些线程共享进程的资源。
  2. 并发与并行

    • 并发(Concurrency)是指两个或多个任务看上去似乎是同时执行的,但在实际的单个CPU情况下,它们只是在快速地交替执行。
    • 并行(Parallelism)则是真正意义上的同时执行,通常需要多核处理器的支持。

二、实现多线程的方式

Java中主要有以下几种创建线程的方式:

  1. 继承Thread

     class MyThread extends Thread {
         
         public void run() {
         
             System.out.println("Thread is running");
         }
     }
    
     public static void main(String[] args) {
         
         MyThread thread = new MyThread();
         thread.start();
     }
    
  2. 实现Runnable接口

     class MyRunnable implements Runnable {
         
         public void run() {
         
             System.out.println("Thread is running");
         }
     }
    
     public static void main(String[] args) {
         
         Thread thread = new Thread(new MyRunnable());
         thread.start();
     }
    
  3. 使用CallableFutureTask

     class MyCallable implements Callable<String> {
         
         public String call() throws Exception {
         
             return "Thread is running";
         }
     }
    
     public static void main(String[] args) throws ExecutionException, InterruptedException {
         
         Callable<String> callable = new MyCallable();
         FutureTask<String> futureTask = new FutureTask<>(callable);
         Thread thread = new Thread(futureTask);
         thread.start();
         System.out.println(futureTask.get()); // 获取返回值
     }
    

三、线程间通信与同步

在多线程编程中,线程间的协调和通信是非常重要的。Java提供了多种方式来实现线程同步和通信:

  1. synchronized关键字:用于方法或代码块,确保同一时间只有一个线程能够执行该方法或代码块。

     public synchronized void synchronizedMethod() {
         
         // critical section
     }
    
  2. ReentrantLock:相比于synchronizedReentrantLock提供了更灵活的锁机制,包括公平锁和非公平锁。

     ReentrantLock lock = new ReentrantLock();
     lock.lock();
     try {
         
         // critical section
     } finally {
         
         lock.unlock();
     }
    
  3. wait()和notify()/notifyAll():用于让线程等待某个条件或者通知其他线程某个条件已经满足。

     public void waitForSomething() throws InterruptedException {
         
         synchronized (this) {
         
             wait();
         }
     }
    
     public void notifySomethingHappened() {
         
         synchronized (this) {
         
             notifyAll();
         }
     }
    
  4. Semaphore:用于控制同时访问特定资源的线程数量,常用于资源池的管理。

     Semaphore semaphore = new Semaphore(5);
     semaphore.acquire();
     try {
         
         // access resource
     } finally {
         
         semaphore.release();
     }
    
  5. CountDownLatch:用于让一个或多个线程等待其他线程完成操作。

     CountDownLatch latch = new CountDownLatch(3);
     new Thread(() -> {
         
         // do work
         latch.countDown();
     }).start();
    
     latch.await();  // 等待所有线程完成
    

四、高级话题:线程池

为了更高效地管理线程资源,Java引入了线程池机制。线程池可以避免频繁创建和销毁线程带来的开销,提高系统性能。Java标准库提供了以下几种线程池:

  1. FixedThreadPool:固定大小的线程池。

     ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
    
  2. CachedThreadPool:可缓存的线程池,根据需要创建新线程。

     ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    
  3. SingleThreadExecutor:单线程化的线程池。

     ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    
  4. ScheduledThreadPool:支持定时及周期性任务执行的线程池。

     ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
     scheduledThreadPool.scheduleAtFixedRate(() -> {
         
         // 执行任务
     }, 1, 2, TimeUnit.SECONDS);  // 延迟1秒后每2秒执行一次
    

五、总结

Java多线程编程是一个庞大而复杂的领域,涉及许多细节和技巧。本文简要介绍了Java多线程的基础概念、实现方式、线程间通信与同步以及线程池的使用。希望通过这篇文章,读者能够对Java多线程编程有一个初步的了解,并能在实际开发中加以运用。无论是提升程序性能还是改善用户体验,多线程编程都是不可或缺的技能。

相关文章
|
7天前
|
编解码 Java 程序员
写代码还有专业的编程显示器?
写代码已经十个年头了, 一直都是习惯直接用一台Mac电脑写代码 偶尔接一个显示器, 但是可能因为公司配的显示器不怎么样, 还要接转接头 搞得桌面杂乱无章,分辨率也低,感觉屏幕还是Mac自带的看着舒服
|
9天前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1568 10
|
1月前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
12天前
|
人工智能 Rust Java
10月更文挑战赛火热启动,坚持热爱坚持创作!
开发者社区10月更文挑战,寻找热爱技术内容创作的你,欢迎来创作!
782 27
|
2天前
|
移动开发 JavaScript 前端开发
💻揭秘!如何用 Vue 3 实现酷炫的色彩魔方游戏✨
本文分享了开发基于Canvas技术的小游戏"色彩魔方挑战"的完整过程。游戏旨在考验玩家的观察力和耐心,通过随机生成的颜色矩阵和一个变化点,玩家需在两幅画布中找出不同的颜色点。文章详细讲解了游戏的核心功能,包括随机颜色矩阵生成、点的闪烁提示、自定义配色方案等。此外,作者展示了使用Vue 3和TypeScript开发的代码实现,带领读者一步步深入了解游戏的逻辑与细节。
103 68
|
2天前
|
存储 前端开发 JavaScript
🚀前端轻松实现网页内容转换:一键复制、保存图片及生成 Markdown
在现代前端开发中,提升用户的交互体验至关重要。本文将详细介绍如何使用 HTML2Canvas 和 Turndown 两个强大的 JavaScript 库,实现将网页选中文本转化为图片并保存或复制到剪贴板,或将内容转换为 Markdown 格式。文章包含核心代码实现、技术细节和功能拓展方向,为开发者提供了一个轻量级的解决方案,提升用户体验。
100 68
|
16天前
|
Linux 虚拟化 开发者
一键将CentOs的yum源更换为国内阿里yum源
一键将CentOs的yum源更换为国内阿里yum源
849 5
|
9天前
|
存储 SQL 关系型数据库
彻底搞懂InnoDB的MVCC多版本并发控制
本文详细介绍了InnoDB存储引擎中的两种并发控制方法:MVCC(多版本并发控制)和LBCC(基于锁的并发控制)。MVCC通过记录版本信息和使用快照读取机制,实现了高并发下的读写操作,而LBCC则通过加锁机制控制并发访问。文章深入探讨了MVCC的工作原理,包括插入、删除、修改流程及查询过程中的快照读取机制。通过多个案例演示了不同隔离级别下MVCC的具体表现,并解释了事务ID的分配和管理方式。最后,对比了四种隔离级别的性能特点,帮助读者理解如何根据具体需求选择合适的隔离级别以优化数据库性能。
232 4
|
2天前
|
人工智能
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
云端问道12期-构建基于Elasticsearch的企业级AI搜索应用陪跑班获奖名单公布啦!
121 1
|
6天前
|
并行计算 PyTorch TensorFlow
Ubuntu安装笔记(一):安装显卡驱动、cuda/cudnn、Anaconda、Pytorch、Tensorflow、Opencv、Visdom、FFMPEG、卸载一些不必要的预装软件
这篇文章是关于如何在Ubuntu操作系统上安装显卡驱动、CUDA、CUDNN、Anaconda、PyTorch、TensorFlow、OpenCV、FFMPEG以及卸载不必要的预装软件的详细指南。
471 2