Java多线程入门介绍

在Java编程中,线程并发是一个核心且复杂的话题,它允许开发者利用现代多核处理器的计算能力,通过并行执行多个任务来优化应用程序的性能。然而,线程并发也带来了数据竞争、死锁、线程饥饿等问题,需要开发者深入理解并发模型及其相关机制。本文将详细介绍Java中线程并发的内容,包括基本概念、使用场景以及常用的关键字和对应的代码。

一、Java线程并发基础

在深入探讨Java线程并发之前,有必要先区分线程(Thread)与进程(Process)的概念。进程是系统进行资源分配和调度的一个独立单元,它拥有独立的内存空间和系统资源。而线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的独立运行的单位。一个进程可以拥有多个线程,这些线程共享进程的资源,包括内存、文件句柄等。
在Java中,线程可以通过继承Thread类或实现Runnable接口来创建。Java虚拟机(JVM)负责线程的调度和执行,它采用抢占式调度模型,即线程的执行时间和顺序由JVM的线程调度器决定,而非由程序员控制。

// 继承Thread类创建线程  
class MyThread extends Thread {  public void run() {  System.out.println("Thread is running");  }  
}  // 实现Runnable接口创建线程  
class MyRunnable implements Runnable {  public void run() {  System.out.println("Runnable is running");  }  
}  // 创建并启动线程  
MyThread thread = new MyThread();  
thread.start();  Thread runnableThread = new Thread(new MyRunnable());  
runnableThread.start();

二、线程同步与通信

在多线程环境下,由于多个线程可能同时访问共享资源,因此必须采取适当的同步机制来避免数据竞争和一致性问题。Java提供了多种同步机制,包括synchronized关键字、volatile关键字、Lock接口及其实现类(如ReentrantLock)、以及wait、notify、notifyAll等方法。

1、 synchronized

synchronized是Java中用于控制多个线程对共享资源的访问,确保同一时刻只有一个线程可以执行某个方法或代码块。它可以修饰方法或代码块。
代码示例:

public class Counter {  private int count = 0;  // synchronized方法  public synchronized void increment() {  count++; // 复合操作,但在synchronized方法中认为是原子的  }  // synchronized代码块  public void decrement() {  synchronized (this) {  count--;  }  }  public synchronized int getCount() {  return count;  }  
}

2、volatile

volatile关键字用于确保变量的修改对所有线程立即可见,它禁止了指令重排序优化,并确保了变量修改的原子性(但仅限于单个变量的读写操作)。
代码示例:

public class FlagController {  private volatile boolean running = true;  public void stopRunning() {  running = false;  }  public boolean isRunning() {  return running;  }  public static void main(String[] args) throws InterruptedException {  FlagController controller = new FlagController();  Thread thread = new Thread(() -> {  while (controller.isRunning()) {  // 执行任务  try {  Thread.sleep(100);  } catch (InterruptedException e) {  Thread.currentThread().interrupt();  }  }  System.out.println("Thread stopped");  });  thread.start();  Thread.sleep(500); // 让线程运行一段时间  controller.stopRunning(); // 停止线程  }  
}

注意: 实际上,volatile在这里仅用于演示变量可见性,而线程的停止通常不建议使用volatile标志位控制,因为这种方式不够优雅且难以处理所有情况(如线程阻塞时)。

3、Lock接口及其实现

Lock接口提供了比synchronized更灵活的锁定机制,它允许在尝试获取锁时设置超时时间、响应中断,以及尝试非阻塞地获取锁。ReentrantLock是Lock接口的一个实现,支持重入性。
代码示例:

import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock;  public class CounterWithLock {  private final Lock lock = new ReentrantLock();  private int count = 0;  public void increment() {  lock.lock();  try {  count++;  } finally {  lock.unlock();  }  }  public int getCount() {  lock.lock();  try {  return count;  } finally {  lock.unlock();  }  }  
}

4、wait/notify/notifyAll

这些方法用于在synchronized块或方法内部实现线程间的通信。wait()使当前线程等待,直到另一个线程调用同一对象的notify()或notifyAll()方法。notifyAll()唤醒在该对象上等待的所有线程。
代码示例:

public class ProducerConsumerQueue {  private final Object lock = new Object();  private int[] queue = new int[10];  private int head = 0, tail = 0;  public void produce(int value) throws InterruptedException {  synchronized (lock) {  while ((tail + 1) % queue.length == head) {  lock.wait(); // 等待队列不满  }  queue[tail] = value;  tail = (tail + 1) % queue.length;  lock.notifyAll(); // 通知等待的消费者  }  }  public int consume() throws InterruptedException {  synchronized (lock) {  while (head == tail) {  lock.wait(); // 等待队列不为空  }  int value = queue[head];  head = (head + 1) % queue.length;  lock.notifyAll(); // 通知等待的生产者  return value;  }  }  
}

三、线程通信与协作

除了上述同步机制外,Java还提供了join、interrupt等方法来实现线程间的通信与协作。

1、join

join方法用于使当前线程等待另一个线程完成。这常用于控制线程的执行顺序,确保某个线程在继续执行之前,另一个线程已经完成其任务。
代码示例:

public class Main {  public static void main(String[] args) throws InterruptedException {  Thread thread = new Thread(() -> {  System.out.println("Thread is running");  try {  Thread.sleep(1000); // 模拟耗时操作  } catch (InterruptedException e) {  Thread.currentThread().interrupt();  }  System.out.println("Thread is finished");  });  thread.start();  thread.join(); // 等待thread线程完成  System.out.println("Main thread continues");  }  
}

2、interrupt

interrupt方法用于中断线程。当一个线程被中断时,它的中断状态会被设置为true。线程可以通过检查中断状态或捕获InterruptedException来响应中断。
注意: 实际上,interrupt并不直接停止线程的执行,而是给线程发送一个中断信号。线程需要通过检查中断状态或捕获InterruptedException来响应这个信号,并适当地停止自己的执行。

四、使用场景

线程并发的使用场景非常广泛,包括但不限于以下几个方面:

1、服务器应用:

在Web服务器、数据库服务器等应用中,通过多线程处理客户端请求,提高并发处理能力。

2、图形用户界面(GUI):

在Java Swing或JavaFX等GUI框架中,事件处理通常是在单独的线程中进行的,以避免界面冻结。

3、数据处理与分析:

在处理大量数据时,可以利用多线程并行处理数据块,加速数据处理速度。

4、游戏开发:

在游戏开发中,多线程可以用于处理游戏逻辑、渲染图形、处理网络通信等任务,提升游戏的响应性和流畅度。

五、总结

Java中的线程并发是一个强大而复杂的特性,它允许开发者编写出高效、响应性强的应用程序。然而,线程并发也带来了数据竞争、死锁、线程饥饿等问题,需要开发者深入理解同步机制、线程间通信与协作等内容。本文介绍了Java中线程并发的基础概念、使用场景,并详细解释了synchronized、volatile、Lock、wait、join、notifyAll等关键字的用法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/53011.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

day-45 全排列 II

思路 与上一题思路相同,代码也基本一致,只是需要全排列不重复 解题过程 可以利用Arrays.sort()函数将nums数组进行排序,这样相同的全排列数字的位置也会相同,可以利用List的contains()函数进行判断,如果不重复则加入答…

【MySQL数据库管理问答题】第7章 MySQL 安全

目录 1. 哪些常见的措施可以用来防范网络安全风险? 2. 请对安全套接字层(SSL)和传输层安全性(TLS)协议加以简要得说明。 3. 请对 ca.pem、server-cert.pem、server-key.pem、ca-key.pem、client-cert.pem、client-ke…

Java面试自我介绍

持续更新中 模块序号目录链接前言介绍1前言地址2介绍地址基础知识3计算机网络地址4操作系统地址5Java基础地址6Java并发地址7Java虚拟机地址中间件8Mysql地址9Redis地址10Elasticsearch地址11RabbitMQ地址12RocketMQ地址框架13分布式系统地址14MyBatis地址15Dubbo地址16Spring地…

【fastapi】fastapi的hello world

新建这样的目录结构 main.py的代码如下 from fastapi import FastAPI from fastapi.templating import Jinja2Templatesapp FastAPI()# 初始化 Jinja2 模板引擎 templates Jinja2Templates(directory"templates")app.get("/") async def home():contex…

《C++打造高效网络爬虫:突破数据壁垒》

在当今信息爆炸的时代,网络爬虫成为了获取大量数据的重要工具。而 C作为一种高效、强大的编程语言,在实现高效网络爬虫方面具有独特的优势。 首先,C的高效性能是实现高效网络爬虫的关键。与其他编程语言相比,C在运行速度和内存管…

网站建设完成后, 做seo必须知道的专业知识之--网络爬虫

网络爬虫,也称为网络蜘蛛或网络机器人,是一种能够自动浏览和采集互联网信息的程序。在大数据时代,网络爬虫技术在信息采集领域发挥着重要作用,通过自动化方式高效获取数据,广泛应用于搜索引擎、数据分析、金融数据采集…

Windows Edge浏览器的兼容性问题

针对Windows Edge浏览器的兼容性问题,我们可以采取一系列措施来尝试修复。以下是一系列详细的解决步骤和策略,旨在帮助用户解决在使用Edge浏览器时遇到的兼容性问题。 一、检查并更新Edge浏览器 1. 自动更新检查 打开Edge浏览器,点击右上角…

海外新闻稿发布:企业如何充分利用数字化媒体进行

在全球数字化进程加速的时代,企业要在激烈的国际市场中脱颖而出,利用数字化媒体进行海外新闻稿发布是一个不可或缺的战略。精确的策略和有效的执行能够帮助企业获得更高的曝光度和市场份额。以下将从多个角度探讨如何充分利用数字化媒体进行海外新闻稿发…

深度学习100问43:什么是过拟合

嘿,咱来聊聊过拟合是什么。 想象一下,有个机器学习的模型就像一个学生在准备考试。如果这个模型对训练数据就像学生把课本上的题目背得超级熟,在训练数据上表现得那叫一个棒,就像学生在做课本上的题时成绩超高。但是呢&#xff…

进阶SpringBoot之 Shiro(3)实现登录拦截和用户认证

Config 配置类添加 Shiro 的内置过滤器 anon:无需认证就能访问 authc:认证才能访问 user:拥有“记住我”功能才能使用 perms:拥有对某个资源的权限才能访问 role:拥有某个角色权限才能访问 package com.demo.shi…

深度学习项目实践——QQ聊天机器人(transformer)(三)功能实现的方法——NoneBot2插件结构与编写

深度学习项目实践——QQ聊天机器人(transformer)(三)功能实现的方法——NoneBot2插件结构与编写 在前两节中,我们详细讲解了QQ聊天的原理、QQ机器人的框架与环境配置的流程。本节将重点介绍NoneBot2的插件构成&#x…

[vue] jszip html-docx-js file-saver 图片,纯文本 ,打包压缩,下载跨域问题

npm install jszip file-saverimport JSZip from jszip; import FileSaver from file-saver;JSZip 创建JSZip实例: const zip new JSZip();创建文件:支持导出纯文本 zip.file("hello.txt", "Hello World\n");创建文件夹&#xf…

pm2 + linux + nginx

pm2 pm2是一个用于管理node项目的工具 前言 有如下两个文件 index.js const express require("express"); const app express(); const port 9999;app.get("/index", (req, res) > {res.json({code:200,msg:"songzx001"}) });app.lis…

PHP:构建高效Web应用的强大语言

PHP:构建高效Web应用的强大语言 在当今的Web开发领域,PHP依然是一个不可忽视的强大工具。自1995年诞生以来,PHP(Hypertext Preprocessor)已经发展成为一种广泛使用的开源脚本语言,特别适用于Web开发并可嵌入HTML中使用。本文将深入探讨PHP的核心优势、最新发展,并通过一…

fpga图像处理实战-均值滤波

均值滤波 均值滤波是一种简单的图像处理技术,主要用于平滑图像,去除噪声。它通过用当前像素邻域的平均值代替该像素值,从而实现图像的平滑处理。这种滤波器在图像处理中被广泛用于减少图像中的随机噪声。 算法原理 均值滤波的基本思想是使用一个固定大小的滑动窗口(通常为…

Web3常见概念

Layer0 到 Layer3 的对比差异 层级定义主要功能举例Layer0基础设施层 提供区块链底层技术和基础设施 Avalanche、Cosmos、Horizen、PolkadotLayer1区块链层提供主要区块链协议和功能,处理交易和智能合约以太坊、Polkadot、EOSLayer2协议增强层优化交易速度和费用&a…

使用 multipass 创建 ubuntu 虚拟机

1. 创建虚拟机 multipass find # 查看镜像 multipass launch -n my-server -c 4 -m 4G -d 10G 24.04 # 创建虚拟机,具体参数可以根据 multipass launch --help 查看查看虚拟机状态 ➜ ~ multipass list Name State IPv4 …

【单片机原理及应用】实验: 8位数码显示器

目录 一、实验目的 二、实验内容 三、实验步骤 四、记录与处理 五、思考 六、成果文件提取链接 一、实验目的 学习8位数码管串行扩展原理,掌握74HC595与动态显示编程方法。 二、实验内容 【参照图表】 (1)创建一个包含80C51固件&#x…

查看 linux 系统信息

文章目录 查看系统信息查看GPU信息 查看系统信息 在Linux系统中,查看系统信息是一项基本而重要的操作。这可以提供关键的系统配置和状态信息,帮助用户和管理员对系统进行监控、诊断和优化。为了全面了解如何查看Linux系统的各种信息,下面的内…

解决npm run dev无法被同局域网访问的问题

解决npm run dev无法被同局域网访问的问题 解决npm run dev无法被同局域网访问的问题引言问题分析解决方案1. 使用 0.0.0.0 作为监听地址a. 对于基于 Node.js 的服务器:b. 对于 Vue CLI 项目: 2. 使用 ngrok 内网穿透3. 配置防火墙4. 使用 Docker 结语 解…