当前位置: 首页 > news >正文

安卓应用开发学习:手机摇一摇功能应用尝试--摇骰子和摇红包

一、引言

前几天,我发布的日志《安卓应用开发学习:查看手机传感器信息》记录了如何查看手机传感器的信息,通过上述的方法,可以看到我的OPPO手机支持19种传感器。本篇日志就记录一下常见的加速度传感器的典型应用——“摇一摇”功能。本应用通过加速度传感器来实现摇骰子或摇红包。最终效果如下:

摇骰子

 

摇红包

 

游戏结束

二、功能实现

加速传感器是最常见的传感器之一,有很多应用的摇手机功能就是用到了这个传感器。本次通过学习相关资料,在我的手机上实现了摇骰子和摇红包两个小应用,并且在摇动手机的过程中手机还会振动。大体的实现方法如下:

1.实现振动功能

1.1先要在AndroidManifest.xml文件中添加如下权限。

<uses-permission android:name="android.permission.VIBRATE" />

1.2 在你创建的Activity中申明一个Vibrator对象。

private Vibrator mVibrator;

1.3在需要实现手机振动功能的代码块中,执行vibrate()方法。

mVibrator.vibrate(300); // 系统检测到摇一摇事件后,震动手机提示用户

该方法参数有两种形式:

一是形如 mVibrator.vibrate(300)  的单参数,表示让手机持续振动指定的毫秒数;

二是形如 mVibrator.vibrate({500, 200, 500}, -1) 的双参数,表示先振动500毫秒,然后停止200毫秒,再振动500毫秒。第二个参数为-1表示无循环,为正数,表示循环次数。

2.摇一摇功能的实现

2.1在你创建的Activity中申明一个SensorManager对象。

private SensorManager mSensorMgr;

2.2重写活动页面的onResume方法,在该方法中注册传感器监听事件,并指定待监听的传感器类型为加速度传感器。

    @Overrideprotected void onResume() {super.onResume();// 给加速度传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);}

2.3重写活动页面的onPause方法,在该方法中注销监听器。

    @Overrideprotected void onPause() {super.onPause();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}

2.3编写一个传感器事件监听器,该监听器继承自SensorEventListener。

在活动页面名称后面添加“implements SensorEventListener”(如下),

public class ShakeActivity extends AppCompatActivity implements SensorEventListener {...}

然后按Alt + Enter,Android Studio 自动添加onSensorChanged方法和onAccuracyChanged方法。

onSensorChanged方法在感应信息变化时触发,业务逻辑就写在这里。在本应用中添加的代码是检测手机晃动的幅度是否大于阀值,一旦大于阀值,就让手机振动500毫秒。

onAccuracyChanged方法在精度改变时触发,一般无需处理。

@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 加速度变更事件// values[0]:X轴,values[1]:Y轴,values[2]:Z轴float[] values = event.values;if ((Math.abs(values[0]) > 15 || Math.abs(values[1]) > 15|| Math.abs(values[2]) > 15)) {mVibrator.vibrate(300); // 系统检测到摇一摇事件后,震动手机提示用户}}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// 当传感器精度改变时回调该方法,一般无需处理}

3.游戏模式的选择

3.1本应用支持2种游戏模式,因此在界面设计上用到了RadioGroup和RadioButton。

<TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:gravity="center_horizontal"android:text="游戏模式:" /><RadioGroupandroid:id="@+id/rg_mode"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_dice"android:layout_width="80dp"android:layout_height="20dp"android:checked="true"android:text="摇骰子" /><RadioButtonandroid:id="@+id/rb_welfare"android:layout_width="80dp"android:layout_height="20dp"android:text="摇红包" /></RadioGroup>

3.2在活动页面声明如下变量:

    private int mMode;  // 游戏模式private final int MODE_DICE = 0;  // 游戏模式1:摇骰子private final int MODE_WELFARE = 1;  // 游戏模式2:摇红包private boolean mState = false;  // 游戏状态private int diceCount;  // 统计摇骰子次数private int welfareNumber;  // 统计红包个数private final int[] welfareArr = {1, 5, 10} ;  // 红包,可根据情况调整

3.2在活动页面中编写单选按钮组事件监听器,该监听器继承自RadioGroup.OnCheckedChangeListener。通过单选按钮的改变触发响应事件,在onCheckedChanged方法中编写游戏模式变更的逻辑代码。

    @Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {// 根据单选按钮结果,设置游戏模式if (checkedId == R.id.rb_dice) {mMode = MODE_DICE;   // 摇骰子模式} else if (checkedId == R.id.rb_welfare) {mMode = MODE_WELFARE;  // 摇红包模式}}
4.游戏的执行逻辑

4.1游戏模式选择。默认是选中了摇一摇模式。

4.2点“开始”按钮。当前是非游戏状态;将变量diceCount和welfareNumber都设为0;将游戏状态变量mState设为Ture;页面中显示“请开始摇手机”;将按钮文本改为停止。游戏过程中游戏模式可随时切换,不会终止游戏。

4.3只有mState为Ture时摇动手机,才会进行检测。当检测到有效摇动时,手机会振动300毫秒,并执行startGame方法(延时300毫秒后执行,避免此方法实际执行次数与振动次数有大的差异。

4.4startGame方法中首先检查游戏模式。

如果是摇骰子模式,则产生三个1-6的随机数(设定为三个骰子)。将本次的结果显示在页面上,并将摇骰子次数统计变量diceCount加1。

如果是摇红包模式,则产生一个1-10的随机数,将该随机数与数组welfareArr中的元素进行对比,如果该随机数在数组中,则在页面中显示中奖信息。获得红包统计变量welfareNumber加1。

5.游戏状态下点“停止”按钮,结束游戏。将按钮文本改为开始;页面中显示摇骰子次数和获得红包个数。

三、代码展示

最终的代码如下:

1. 界面设计文件  activity_shake.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".ShakeActivity"><TextViewandroid:id="@+id/tv_title"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="20dp"android:text="摇一摇"android:textSize="28sp"android:textStyle="bold"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><LinearLayoutandroid:id="@+id/ll_mode"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="10dp"android:layout_marginTop="30dp"android:layout_marginEnd="10dp"android:orientation="horizontal"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/tv_title"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:gravity="center_horizontal"android:text="游戏模式:" /><RadioGroupandroid:id="@+id/rg_mode"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioButtonandroid:id="@+id/rb_dice"android:layout_width="80dp"android:layout_height="20dp"android:checked="true"android:text="摇骰子" /><RadioButtonandroid:id="@+id/rb_welfare"android:layout_width="80dp"android:layout_height="20dp"android:text="摇红包" /></RadioGroup></LinearLayout><Buttonandroid:id="@+id/btn_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:text="开始"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/ll_mode" /><TextViewandroid:id="@+id/tv_shake"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="30dp"android:textSize="17sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/btn_start" /></androidx.constraintlayout.widget.ConstraintLayout>

2.逻辑代码 ShakeActivity.java

import androidx.appcompat.app.AppCompatActivity;import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.TextView;import java.util.Arrays;
import java.util.Locale;
import java.util.Random;public class ShakeActivity extends AppCompatActivity implements SensorEventListener,RadioGroup.OnCheckedChangeListener, View.OnClickListener {private final static String TAG = "ShakeActivity";private TextView tv_shake; // 声明一个文本视图对象private SensorManager mSensorMgr; // 声明一个传感管理器对象private Vibrator mVibrator; // 声明一个震动器对象private Button btn_start;  // 开始按钮private int mMode;  // 游戏模式private final int MODE_DICE = 0;  // 游戏模式1:摇骰子private final int MODE_WELFARE = 1;  // 游戏模式2:摇红包private boolean mState = false;  // 游戏状态private int diceCount;  // 统计摇骰子次数private int welfareNumber;  // 统计红包个数private final int[] welfareArr = {1, 5, 10} ;  // 红包 , 20, 50, 100, 500, 1000@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_shake);// 游戏模式选择按钮组RadioGroup rg_mode = findViewById(R.id.rg_mode);rg_mode.setOnCheckedChangeListener(this);tv_shake = findViewById(R.id.tv_shake);btn_start = findViewById(R.id.btn_start);btn_start.setOnClickListener(this);  // 开始按钮点击监听// 从系统服务中获取传感管理器对象mSensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);// 从系统服务中获取震动器对象mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);mMode = MODE_DICE;  // 单选按钮初始状态选中的遥骰子}@Overrideprotected void onPause() {super.onPause();mSensorMgr.unregisterListener(this); // 注销当前活动的传感监听器}@Overrideprotected void onResume() {super.onResume();// 给加速度传感器注册传感监听器mSensorMgr.registerListener(this,mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);}@Overridepublic void onSensorChanged(SensorEvent event) {if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { // 加速度变更事件// values[0]:X轴,values[1]:Y轴,values[2]:Z轴float[] values = event.values;if ((Math.abs(values[0]) > 30 || Math.abs(values[1]) > 30|| Math.abs(values[2]) > 30)) {if (mState) {mVibrator.vibrate(300); // 系统检测到摇一摇事件后,震动手机提示用户new Handler().postDelayed(() -> {// 延时后要执行的代码startGame();}, 300); // 延迟时间毫秒}}}}@Overridepublic void onAccuracyChanged(Sensor sensor, int accuracy) {// 当传感器精度改变时回调该方法,一般无需处理}@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {// 根据单选按钮结果,设置游戏模式if (checkedId == R.id.rb_dice) {mMode = MODE_DICE;  // 摇骰子模式} else if (checkedId == R.id.rb_welfare) {mMode = MODE_WELFARE;  // 摇红包模式}}@Overridepublic void onClick(View v) {if (v.getId() == R.id.btn_start) {if (mState) {  // 点击时处于游戏状态btn_start.setText("开始");String info = String.format(Locale.CHINESE, "%s%d次,%s%d个。","本次摇骰子", diceCount, "获得红包", welfareNumber);tv_shake.setText(info);} else {  // 点击时处于非游戏状态diceCount = 0;welfareNumber = 0;tv_shake.setText("请开始摇手机");btn_start.setText("停止");}mState = !mState;}}private void startGame() {String info = "";        // 检查游戏模式if (mMode == MODE_DICE) { // 摇骰子// 设定有3个骰子,产生3个1-6的随机数Random random = new Random();int dice1 = random.nextInt(6) + 1;int dice2 = random.nextInt(6) + 1;int dice3 = random.nextInt(6) + 1;info = String.format(Locale.CHINESE,"%s%d,%d,%d。", "您摇出的骰子点数是:",dice1, dice2, dice3);diceCount +=1;} else if (mMode == MODE_WELFARE) {  // 摇红包int lottery;info = "很遗憾,您没有中奖";// 生成一个0-10的随机数int randomNumber = (int)(Math.random() * 11);   // 1001Log.d(TAG, "随机数为:" + randomNumber);// 检查该随机数是否在红包列表中boolean isInArray = Arrays.stream(welfareArr).anyMatch(n -> n == randomNumber);if (isInArray) {lottery = randomNumber;info = String.format(Locale.CHINESE,"%s%d%s", "恭喜您中了", lottery,"元!");welfareNumber +=1;}}tv_shake.setText(info);}
}

相关文章:

安卓应用开发学习:手机摇一摇功能应用尝试--摇骰子和摇红包

一、引言 前几天&#xff0c;我发布的日志《安卓应用开发学习&#xff1a;查看手机传感器信息》记录了如何查看手机传感器的信息&#xff0c;通过上述的方法&#xff0c;可以看到我的OPPO手机支持19种传感器。本篇日志就记录一下常见的加速度传感器的典型应用——“摇一摇”功…...

HTML中的<fieldset>标签元素框的使用

HTML 提供的 <fieldset> 标签用于在表单中分组相关元素。 <fieldset> 标签会在相关元素周围绘制一个框。 <legend> 标签为 fieldset 元素定义标题。 语法如下&#xff1a; <fieldset><legend>标题</legend><!-- 元素内容... -->…...

Linux驱动入门实验班——SR501红外模块驱动(附百问网视频链接)

目录 一、工作方式 二、接口图 三、编写思路 1.构造file_operations结构体 2.实现read函数 3.编写入口函数 4.编写中断处理函数 5.编写出口函数 6.声明出入口函数以及协议 四、源码 五、课程链接 一、工作方式 SR501人体红外感应模块有两种工作模式&#xff1a; …...

windows C++- Com技术简介(上)

在介绍C和winrt与COM组件技术的关系之前&#xff0c;有必要介绍一下com组件技术&#xff0c;这项技术比较古老&#xff0c;但是它一直作为windows的基石存在。COM 是一类独立于平台且面向对象的分布式系统&#xff0c;用于创建可交互的二进制软件组件。 COM 技术是 Microsoft O…...

Jenkins持续集成工具学习

一、从装修厨房看项目开发效率优化 二、持续集成工具 三、JavaEE项目部署方式对比 四、JenkinsSVN持续集成环境搭建 五、JenkinsGitHub持续集成环境搭建...

Redis:查询是否包含某个字符/字符串之三

上一篇&#xff1a;Redis&#xff1a;查询是否包含某个字符/字符串之二-CSDN博客 摘要&#xff1a; 遍历key&#xff0c;在跟进value的类型遍历value是否包含指定字符串 search_strings &#xff0c;这里使用redis-py库&#xff0c;默认只能处理utf-8编码&#xff0c;如果存在…...

【Redis】数据类型详解及其应用场景

目录 Redis 常⻅数据类型预备知识基本全局命令小结 数据结构和内部编码单线程架构引出单线程模型为什么单线程还能这么快 Redis 常⻅数据类型 Redis 提供了 5 种数据结构&#xff0c;理解每种数据结构的特点对于 Redis 开发运维⾮常重要&#xff0c;同时掌握每种数据结构的常⻅…...

PARA-Drive:设计并行模型实现端到端自动驾驶

论文链接 https://openaccess.thecvf.com/content/CVPR2024/papers/Weng_PARA-Drive_Parallelized_Architecture_for_Real-time_Autonomous_Driving_CVPR_2024_paper.pdfhttps://openaccess.thecvf.com/content/CVPR2024/papers/Weng_PARA-Drive_Parallelized_Architecture_fo…...

vs2022 x64 C/C++和汇编混编 遇到的坑

vs2022 x64 C/C和汇编混编 遇到的坑 遇到的问题二、问题复现1.出错代码2.问题分析2.1 堆栈对齐问题 3.解决方案 总结奇数和偶数个寄存器的影响为什么 sub rsp, 8 对奇数个寄存器有用&#xff1f;结论 遇到的问题 0x00007FFFFAE24A29 (msvcp140.dll)处(位于 TestCompileConsole…...

PHP概述、环境搭建与基本语法讲解

目录 【学习目标、重难点知识】 什么是网站&#xff1f; 1. PHP 介绍 1.1. PHP 概述 1.1.1. PHP 是什么&#xff1f; 1.1.2. PHP 都能做什么&#xff1f; 1.2. PHP 环境搭建 1.2.1. PhpStudy 2. PHP 基本语法 2.1. PHP 语法入门 2.1.1. 第一个 PHP 程序 2.1.2. PHP …...

实现信创Linux麦克风摄像头录制(源码,银河麒麟、统信UOS)

随着信创国产化浪潮的来临&#xff0c;在国产操作系统上的应用开发的需求越来越多&#xff0c;其中一个就是需要在银河麒麟或统信UOS上实现录制摄像头视频和麦克风声音&#xff0c;将它们录制成一个mp4文件。那么这个要如何实现了&#xff1f; 一. 技术方案 要完成这些功能&a…...

深度学习9--目标检测

1.概念介绍 目标检测不仅可以检测数字&#xff0c;而且可以检测动物的种类、汽车的种类等。例如&#xff0c;自动驾驶车辆需要自动识别前方物体是车辆还是行人&#xff0c;需要自动识别道路两 旁的指示牌和前方的红绿灯颜色。对于自动检测的算法&#xff0c;有两个要求&#xf…...

第131天:内网安全-横向移动Kerberos 攻击SPN扫描WinRMWinRSRDP

案例一&#xff1a;域横向移动-RDP-明文&NTLM RDP利用的三种方式 1.直接在当前被控主机上进行远程连接 2.建立节点进行连接 3.端口转发&#xff0c;&#xff08;访问当前主机的2222端口等于访问目标的3389&#xff09; 第一种方式(动静太大) 直接利用被控主机进行远程连接…...

微信小程序的四种弹窗使用

​ 在做小程序的过程中&#xff0c;弹窗也算是非常实用的功能了&#xff0c;这几天写的几个功能就用到了弹窗&#xff0c;也可能是初学者的问题&#xff0c;比较菜&#xff0c;想找一个可以带图片的自定义的弹窗&#xff0c;&#xff0c;这里简单介绍一下官方封装好的四个弹窗…...

我的第一个CUDA程序

MatAdd算法 实现两个矩阵对应元素相加 #include <stdio.h> #include <stdlib.h>// 矩阵加法函数 void MatAdd(int height, int width) {// 在主机内存中为 A、B 和 C 分配内存float* A (float*)malloc(height * width * sizeof(float));float* B (float*)malloc…...

workerman下的webman路由浏览器跨域的一种问题

软件版本 "php": ">7.2", "workerman/webman-framework": "^1.5.0",问题情景 使用“分组路由”做API接口前后端分离跨域&#xff0c;在接口测试工具调试是能正常获取数据的&#xff1b;但在网页浏览器上调试就遇到了CORS、404的错…...

Windows11 -MASKRCNN-部署测试

文章目录 Detectron2环境配置搭建python 环境安装Cuda \CUDNN 、PyTorch、 torchvision、cudatoolkit1、Cuda \CUDNN2、 PyTorch、 torchvision、cudatoolkit进入python测试&#xff1a;错误信息 3、detectron2环境在安装detecteron中&#xff0c;遇到报错&#xff1a;编译的时…...

函数(子程序)的常见、易混淆概念详解【对初学者有帮助】

C语⾔中的函数也被称做子程序&#xff0c;意思就是⼀个完成某项特定的任务的⼀小段代码。 C语⾔标准中提供了许多库函数&#xff0c;点击下面的链接可以查看c语言的库函数和头文件。 C/C官⽅的链接&#xff1a;https://zh.cppreference.com/w/c/header 目录 一、函数头与函…...

TiDB-从0到1-DM工具

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇TiDB-从0到1-集群扩缩容TiDB-从0到1-数据导出导入TiDB-从0到1-BR工具 一、DM原理 支持全量抽取数据\检测新的数据变化同步到下游实例…...

AppScan——Web 应用安全扫描的得力工具

一、引言 在当今数字化时代&#xff0c;Web 应用成为企业业务的重要支撑&#xff0c;但同时也面临着各种安全威胁。AppScan 作为一款专业的 Web 应用安全扫描工具&#xff0c;为保障 Web 应用的安全性提供了有力的支持。本文将对 AppScan 进行详细介绍&#xff0c;包括其功能、…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...