【iOS】---pthread,NSThread

2023-05-16

在iOS中多线程开发有四种方式,在之前我们浅浅了解了一下GCD,这期来看看pthread和NSThread
在这里插入图片描述


pehread

pthread简介

pthread 是一套通用的多线程的 API,可以在Unix / Linux / Windows 等系统跨平台使用,使用 C 语言编写,需要程序员自己管理线程的生命周期,使用难度较大。
POSIX 线程(英语:POSIX Threads,常被缩写 为 Pthreads)是 POSIX 的线程标准,定义了创建和操纵线程的一套 API。
实现 POSIX 线程标准的库常被称作 Pthreads,一般用于 Unix-like POSIX 系统,如 Linux、Solaris。但是 Microsoft Windows 上的实现也存在,例如直接使用 Windows API 实现的第三方库 pthreads-w32;而利用 Windows 的 SFU/SUA 子系统,则可以使用微软提供的一部分原生 POSIX API。(维基百科)

pthread使用方法

1.首先要包含头文件#import <pthread.h>
2.其次要创建线程,并开启线程执行任务

//
//  main.m
//  pthread
//
//  Created by 王璐 on 2023/5/6.
//

#import <Foundation/Foundation.h>
#import <pthread.h>
void *run(void *param) {
    
    NSLog(@"1-> %@", [NSThread currentThread]);
    NSLog(@"2-> %@", [NSThread currentThread]);
    NSLog(@"3-> %@", [NSThread currentThread]);
    NSLog(@"4-> %@", [NSThread currentThread]);
    NSLog(@"5-> %@", [NSThread currentThread]);
    NSLog(@"6-> %@", [NSThread currentThread]);
    NSLog(@"7-> %@", [NSThread currentThread]);
    return NULL;
}
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        pthread_t myThread;
        int res = pthread_create(&myThread, NULL, run, NULL);
        if (res == 0) {
            NSLog(@"创建成功");
        }
        pthread_detach(myThread);
        NSLog(@"%@", [NSThread currentThread]);
    }
    return 0;
}


请添加图片描述请添加图片描述
每次运行时结果不一样,这个问题还没能解决。
pthread_create(&thread, NULL, run, NULL); 中各项参数含义:

第一个参数&thread是线程对象,指向线程标识符的指针
第二个是线程属性,可赋值NULL
第三个run表示指向函数的指针(run对应函数里是需要在新线程中执行的任务)
第四个是运行函数的参数,可赋值NULL

pthread其他方法

  • pthread_create() 创建一个线程
  • pthread_exit() 终止当前线程
  • pthread_cancel() 中断另外一个线程的运行
  • pthread_join() 阻塞当前的线程,直到另外一个线程运行结束
  • pthread_attr_init() 初始化线程的属性
  • pthread_attr_setdetachstate() 设置脱离状态的属性(决定这个线程在终止时是否可以被结合)
  • pthread_attr_getdetachstate() 获取脱离状态的属性
  • pthread_attr_destroy() 删除线程的属性
  • pthread_kill() 向线程发送一个信号

NSThread

NSThread 是苹果官方提供的,使用起来比 pthread 更加面向对象,简单易用,可以直接操作线程对象。不过也需要需要程序员自己管理线程的生命周期(主要是创建),我们在开发的过程中偶尔使用 NSThread。比如我们会经常调用[NSThread currentThread]来显示当前的进程信息

创建,启动线程

  • 先创建线程,在启动线程
// 1. 创建线程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
// 2. 启动线程
[thread start];    // 线程一启动,就会在线程thread中执行self的run方法

// 新线程调用方法,里边为需要执行的任务
- (void)run {
     NSLog(@"%@", [NSThread currentThread]);
}

请添加图片描述

  • 创建线程后自动启动线程
// 1. 创建线程后自动启动线程
[NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];

// 新线程调用方法,里边为需要执行的任务
- (void)run {
     NSLog(@"%@", [NSThread currentThread]);
}

在这里插入图片描述

  • 隐式创建并启动线程
// 1. 隐式创建并启动线程
[self performSelectorInBackground:@selector(run) withObject:nil];

// 新线程调用方法,里边为需要执行的任务
- (void)run {
     NSLog(@"%@", [NSThread currentThread]);
}

请添加图片描述

// 获得主线程
+ (NSThread *)mainThread;    

// 判断是否为主线程(对象方法)
- (BOOL)isMainThread;

// 判断是否为主线程(类方法)
+ (BOOL)isMainThread;    

// 获得当前线程
NSThread *current = [NSThread currentThread];

// 线程的名字——setter方法
- (void)setName:(NSString *)n;    

// 线程的名字——getter方法
- (NSString *)name;    

  • 线程状态控制方法
    • 启动线程方法
- (void)start;
// 线程进入就绪状态 -> 运行状态。当线程任务执行完毕,自动进入死亡状态
    • 阻塞(暂停)线程方法
+ (void)sleepUntilDate:(NSDate *)date;
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
// 线程进入阻塞状态

    • 强制停止线程
+ (void)exit;
// 线程进入死亡状态
  • 线程之间的通信
    在开发中,我们经常会在子线程进行耗时操作,操作结束后再回到主线程去刷新 UI。这就涉及到了子线程和主线程之间的通信。我们先来了解一下官方关于 NSThread 的线程间通信的方法。
// 在主线程上执行操作
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray<NSString *> *)array;
  // equivalent to the first method with kCFRunLoopCommonModes

// 在指定线程上执行操作
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

// 在当前线程上执行操作,调用 NSObject 的 performSelector:相关方法
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

举例一个加载图片的demo:

/**
 * 创建一个线程下载图片
 */
- (void)downloadImageOnSubThread {
    // 在创建的子线程中调用downloadImage下载图片
    [NSThread detachNewThreadSelector:@selector(downloadImage) toTarget:self withObject:nil];
}

/**
 * 下载图片,下载完之后回到主线程进行 UI 刷新
 */
- (void)downloadImage {
    NSLog(@"current thread -- %@", [NSThread currentThread]);
    
    // 1. 获取图片 imageUrl
    NSURL *imageUrl = [NSURL URLWithString:@"https://ysc-demo-1254961422.file.myqcloud.com/YSC-phread-NSThread-demo-icon.jpg"];
    
    // 2. 从 imageUrl 中读取数据(下载图片) -- 耗时操作
    NSData *imageData = [NSData dataWithContentsOfURL:imageUrl];
    // 通过二进制 data 创建 image
    UIImage *image = [UIImage imageWithData:imageData];
    
    // 3. 回到主线程进行图片赋值和界面刷新
    [self performSelectorOnMainThread:@selector(refreshOnMainThread:) withObject:image waitUntilDone:YES];
}

/**
 * 回到主线程进行图片赋值和界面刷新
 */
- (void)refreshOnMainThread:(UIImage *)image {
    NSLog(@"current thread -- %@", [NSThread currentThread]);
    
    UIButton* button = [UIButton buttonWithType:UIButtonTypeClose];
    button.frame = CGRectMake(100, 100, 100, 100);
    [button setImage:image forState:UIControlStateNormal];
    [self.view addSubview:button];
}

在这里插入图片描述

NSThread线程安全和线程同步

线程安全

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作(更改变量),一般都需要考虑线程同步,否则的话就可能影响线程安全。

线程同步

可理解为线程 A 和 线程 B 一块配合,A 执行到一定程度时要依靠线程 B 的某个结果,于是停下来,示意 B 运行;B 依言执行,再将结果给 A;A 再继续操作。

火车票售卖


@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, assign) int ticketSurplusCount;
@property (nonatomic, strong) NSThread *ticketSaleWindow1;
@property (nonatomic, strong) NSThread *ticketSaleWindow2;



/**
 * 初始化火车票数量、卖票窗口(非线程安全)、并开始卖票
 */
- (void)initTicketStatusNotSave {
    // 1. 设置剩余火车票为 10
    self.ticketSurplusCount = 10;
    
    // 2. 设置北京火车票售卖窗口的线程
    self.ticketSaleWindow1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketNotSafe) object:nil];
    self.ticketSaleWindow1.name = @"北京火车票售票窗口";
    
    // 3. 设置上海火车票售卖窗口的线程
    self.ticketSaleWindow2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketNotSafe) object:nil];
    self.ticketSaleWindow2.name = @"上海火车票售票窗口";
    
    // 4. 开始售卖火车票
    [self.ticketSaleWindow1 start];
    [self.ticketSaleWindow2 start];

}

/**
 * 售卖火车票(非线程安全)
 */
- (void)saleTicketNotSafe {
    while (1) {
        //如果还有票,继续售卖
        if (self.ticketSurplusCount > 0) {
            self.ticketSurplusCount --;
            NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@", self.ticketSurplusCount, [NSThread currentThread].name]);
            [NSThread sleepForTimeInterval:0.2];
        }
        //如果已卖完,关闭售票窗口
        else {
            NSLog(@"所有火车票均已售完");
            break;
        }
    }
}

两个线程相互竞争,得到票数是错乱的,这样显然不符合我们的需求,所以我们需要考虑线程安全问题。
请添加图片描述

NSThread 线程安全

线程安全解决方案:可以给线程加锁,在一个线程执行该操作的时候,不允许其他线程进行操作。iOS 实现线程加锁有很多种方式。@synchronized、 NSLock、NSRecursiveLock、NSCondition、NSConditionLock、pthread_mutex、dispatch_semaphore、OSSpinLock、atomic(property) set/ge等等各种方式。为了简单起见,这里不对各种锁的解决方案和性能做分析,只用最简单的@synchronized来保证线程安全,从而解决线程同步问题。

/**
 * 初始化火车票数量、卖票窗口(线程安全)、并开始卖票
 */
- (void)initTicketStatusSave {
    // 1. 设置剩余火车票为 10
    self.ticketSurplusCount = 10;
    
    // 2. 设置北京火车票售卖窗口的线程
    self.ticketSaleWindow1 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketSafe) object:nil];
    self.ticketSaleWindow1.name = @"北京火车票售票窗口";
    
    // 3. 设置上海火车票售卖窗口的线程
    self.ticketSaleWindow2 = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicketSafe) object:nil];
    self.ticketSaleWindow2.name = @"上海火车票售票窗口";
    
    // 4. 开始售卖火车票
    [self.ticketSaleWindow1 start];
    [self.ticketSaleWindow2 start];
    
}

/**
 * 售卖火车票(线程安全)
 */
- (void)saleTicketSafe {
    while (1) {
        // 互斥锁
        @synchronized (self) {
            //如果还有票,继续售卖
            if (self.ticketSurplusCount > 0) {
                self.ticketSurplusCount --;
                NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%d 窗口:%@", self.ticketSurplusCount, [NSThread currentThread].name]);
                [NSThread sleepForTimeInterval:0.2];
            }
            //如果已卖完,关闭售票窗口
            else {
                NSLog(@"所有火车票均已售完");
                break;
            }
        }
    }
}

请添加图片描述

线程的状态转换

当我们新建一条线程NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];,在内存中的表现为:
请添加图片描述
当调用[thread start];后,系统把线程对象放入可调度线程池中,线程对象进入就绪状态,如下图所示。请添加图片描述
当然,可调度线程池中,会有其他的线程对象,如下图所示。在这里我们只关心左边的线程对象。请添加图片描述

下边我们来看看当前线程的状态转换:

  • 如果CPU现在调度当前线程对象,则当前线程对象进入运行状态,如果CPU调度其他线程对象,则当前线程对象回到就绪状态。
  • 如果CPU在运行当前线程对象的时候调用了sleep方法\等待同步锁,则当前线程对象就进入了阻塞状态,等到sleep到时\得到同步锁,则回到就绪状态。
  • 如果CPU在运行当前线程对象的时候线程任务执行完毕\异常强制退出,则当前线程对象进入死亡状态。请添加图片描述

NSThread线程属性

name属性:设置线程的名字

NSThread *thread = [[NSThread alloc] initWithBlock:^{
    NSLog(@"线程:%@ start",[NSThread currentThread]);
 }];
thread.name = @"测试线程";
[thread start];

qualityOfService属性:设置线程优先级

typedef NS_ENUM(NSInteger, NSQualityOfService) {
    NSQualityOfServiceUserInteractive = 0x21,
    NSQualityOfServiceUserInitiated = 0x19,
    NSQualityOfServiceUtility = 0x11,
    NSQualityOfServiceBackground = 0x09,
    NSQualityOfServiceDefault = -1
} API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

NSQualityOfServiceUserInteractive 优先级最高,从上到下依次降低,NSQualityOfServiceDefault 为默认优先级。

测试:请添加图片描述

//qualityOfService属性:设置线程优先级
- (void)qualityOfServiceStudy {
    NSThread *thread1 = [[NSThread alloc] initWithBlock:^{
        NSLog(@"\n 线程:%@ start",[NSThread currentThread]);
    }];
    thread1.name = @"测试线程 1 ";
    [thread1 start];
    
    NSThread *thread2 = [[NSThread alloc] initWithBlock:^{
        NSLog(@"\n 线程:%@ start",[NSThread currentThread]);
    }];
    thread2.qualityOfService = NSQualityOfServiceUserInteractive;
    thread2.name = @"测试线程 2 ";
    [thread2 start];
}

虽然 thread1 先于 thread2 start,但thread1优先级为默认,而thread2优先级为NSQualityOfServiceUserInteractive,在执行时,thread2 先于 thread1执行。

其他属性

    • @property (class, readonly, copy) NSArray<NSNumber *> *callStackReturnAddresses //线程的调用会有函数的调用,该属性返回的就是 该线程中函数调用的虚拟地址数组。
    • @property (class, readonly, copy) NSArray<NSString *> *callStackSymbols //该属性以符号的形式返回该线程调用函数。
      //callStackReturnAddress和callStackSymbols这两个函数可以同NSLog联合使用来跟踪线程的函数调用情况,是编程调试的重要手段。
    • @property (readonly, retain) NSMutableDictionary *threadDictionary; //每个线程有自己的堆栈空间,线程内维护了一个键-值的字典,它可以在线程里面的任何地方被访问。
      //你可以使用该字典来保存一些信息,这些信息在整个线程的执行过程中都保持不变。
      //比如,你可以使用它来存储在你的整个线程过程中 Run loop 里面多次迭代的状态信息。
    • @property (class, readonly, strong) NSThread *mainThread; // 获取主线程
    • @property (class, readonly, strong) NSThread *currentThread;// 获取当前线程
    • @property NSUInteger stackSize; // 线程使用堆栈大小,默认512k
    • @property (readonly) BOOL isMainThread; // 是否是主线程
    • @property (class, readonly) BOOL isMainThread ; // reports whether current thread is main
    • @property (readonly, getter=isExecuting) BOOL executing ; // 线程是否正在执行
    • @property (readonly, getter=isFinished) BOOL finished ; // 线程是否执行完毕
    • @property (readonly, getter=isCancelled) BOOL cancelled; // 线程是否取消

请添加图片描述
请添加图片描述
请添加图片描述
demo地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【iOS】---pthread,NSThread 的相关文章

  • 从按钮执行 Segue 时应用程序冻结

    我的故事板中有一个按钮 它呈现一个带有模式序列的视图控制器 每次按下此按钮时 应用程序都会冻结 没有崩溃 也没有错误消息 prepareForSegue被调用 所有应该存在的视图控制器都在代码中prepareForSegue 但它们不会出现
  • TableViewController 的 viewDidLoad 未触发

    我一直在关注这个tutorial http www appcoda com ios programming sidebar navigation menu 有一个滑出式菜单 我添加了一个 TableViewController 它将显示文章
  • 使用 MapKit 的地形和卫星视图

    我是 Mapkit View 的新手 当我给出没有目的地的纬度和经度时 我想显示 MapKit中是否可以通过地形 卫星视图来显示地图 有教程链接吗 我看过一些访问 Google 地图 API html 文件 的示例 有必要吗 或者您可以通过
  • 叠加 SKScene 未显示

    我正在尝试将 SKScene 覆盖在 SCNScene 上 当我在模拟器和 iPhone6 上运行我的应用程序时 overlayScene SKScene 按预期显示 但是当我尝试在 iPhone5 上运行它 尝试了 2 个不同的设备 时
  • 是否可以跨 2 个不同的 iOS 应用程序访问数据?

    假设我在 App1 中存储了一些 ID 数据 并希望在同一设备上的 App2 中访问它 平台上可以这样吗 如果没有的话有什么解决方法吗 您可以使用iOS 钥匙扣 http developer apple com library ios do
  • React Native - NSNumber 无法转换为 NSString

    下面是我的反应组件的一部分 我有一个名为 daysUntil 的道具进入此组件 其中包含一个数字 在此示例中 传递数字 0 导致 fontWeight 函数返回 700 render function return
  • 如何在 Swift 中“生成”闭包类型别名?

    为了使我的代码更易于阅读 我在 Swift 中对各种类型的闭包使用类型别名 我有以下基本的闭包集 public typealias FailureClosure error NSError gt Void public typealias
  • 在 iOS 中发送音频文件和 JSON 字符串

    我正在尝试将音频文件和 JSON 字符串发送到 PHP 服务器 使用以下代码将发送 JSON 但文件到达时为空 如果我将 JSON 块放在音频块下方 文件将完全到达 但 JSON 为空 有什么想法吗 void sendFile NSStri
  • 在phonegap中播放本地声音

    我有一个 wav文件在我的www文件夹 我正在使用 jQuery 和以下代码 警报响起 但声音不播放 难道我做错了什么
  • CSS 安全区域属性在 iPhone X 上不起作用

    就我而言 我正在 iPhone X 上运行一个 Web 应用程序 我尝试在顶部添加一个填充 以使用 Webkit 的安全区域 css 属性将我的身体推到安全区域padding top constant safe area inset top
  • 如何在javascript中计算日出和日落?

    我正在使用appcelerator titan开发一个IOS应用程序 我想让我的应用程序在日出和日落时向用户发送本地通知 解决这个问题的一个好工具是使用 YQL 的雅虎天气 但是 雅虎天气仅供非商业用途 我正在尝试找到一个javascrip
  • UICollectionViewFlowLayout 使其布局无效后重绘单元格

    当您使布局无效时UICollectionViewFlowLayout它为每个单元格创建了一堆新的布局属性 然而 它不会告诉您的单元格重新绘制 这会导致任何图层绘图变形 我不想告诉我的集合重新加载其数据 因为这会删除流属性之间的任何良好转换
  • 尽早检测有问题的 XIB 视图

    我的笔尖名称有一个拼写错误 当我推向导航控制器时 它在代码中被破坏了 弄清楚它并没有花太长时间 但我认为最好尽早断言格式良好 以便更容易弄清楚 问题是它不是零 它只是无法从笔尖正确地形成自己 在 initWithNib 之后是否有更好的断言
  • 如何将 RGB 值转换为十六进制字符串 iOS swift

    我想将 RGB 值转换为十六进制字符串 我将十六进制转换为 RGB 如下所示 但反之亦然 func hexStringToRGB hexString String gt red CGFloat green CGFloat blue CGFl
  • iOS UITableView:使用 CAGradientLayer 将背景颜色指定为渐变

    我刚刚开始使用 Xcode 4 3 中的主从视图模板 我试图更改主视图的背景颜色并将其设置为颜色渐变 这是我尝试过的 Colors m import Colors h implementation Colors UIColor naviga
  • 我的 iPhone 6 获取 iPhone 5 媒体查询

    我不明白这里发生了什么事 我在 CSS 媒体查询中专门针对 iphone 5 media only screen and min device width 320px and max device width 568px some div
  • 从应用程序打开/关闭 iPhone 的 Wifi

    我需要打开或关闭 iPhone 中的 wifi 有什么方法可以做到吗 还是被禁止了 私有框架 所有使用公共 SDK 编写的应用程序都经过沙箱处理 他们只能访问苹果认为可以在该沙箱中使用的属性和数据 恐怕 Wi fi 不在列表中 请看一下这个
  • FIRApp 链接器错误 [“_OBJC_CLASS_$_FIRApp”]

    我已经搜索过 SO 和 Google 但找不到有效的答案 我已经在多个项目中使用了新的 Firebase Cocoapod 但是现在 当将其添加到不同的项目时 我收到以下错误 我正在使用 Xcode 7 3 1 和 cocoapods 1
  • 如何动态添加XCTestCase

    我正在为一个白标签项目编写 UI 测试 其中每个应用程序都有一组不同的菜单项 测试点击每个菜单项并截取屏幕截图 使用快车道快照 https docs fastlane tools actions snapshot 目前这一切都发生在一个内部
  • Textview 中心文本对齐 IOS 7

    void observeValueForKeyPath NSString keyPath ofObject id object change NSDictionary change context void context NSLog He

随机推荐

  • Spring Security --- formLogin配置

    目录 环境准备 配置自定义登录表单页面 配置登录成功的跳转页面方式 配置登录失败的跳转页面方式 前端表单参数获取 CustomWebSecurityConfigurerAdapter配置类代码示例 环境准备 创建springboot项目引入
  • 手写Spring框架---IOC容器实现

    目录 框架具备的最基本功能 实现容器前奏 创建注解 提取标记对象 extractPacakgeClass里面需要完成的事情 获取项目类加载器的目的 为什么不让用户传入绝对路径 类加载器ClassLoader 统一资源定位符URL Class
  • ECharts---X轴文字显示不全

    原因 xff1a X轴标签文字过多导致显示不全解决方法 xff1a 一 xAxis 中添加 xAxis axisLabel 属性 axisLabel是用来设置x轴的刻度以及一些参数的设置 xff1a 1 interval设置的是间隔数 xf
  • MyBatis-plus二级缓存整合Redis 分页中Count缓存createCacheKey 与 getCountCacheKey 缓存Hash值不一致导致数组越界

    当前使用版本 新版本同样存在此问题 MyBatis plus 3 4 1该问题是如何引起的 在使用Redis代理二级缓存中发现存在两个Count缓存 xff0c 并且总是获取错的Count缓存Count缓存createCacheKey的 与
  • Ubuntu16.04安装谷歌浏览器

    Ubuntu16 04安装谷歌浏览器 Ubuntu16 04安装谷歌浏览器分为3步 xff1a 1 下载安装包 2 安装谷歌浏览器 3 启动谷歌浏览器 1 下载谷歌浏览器安装包 使用Ubuntu系统自身携带的火狐浏览器 xff0c 访问谷歌
  • Mybatis一级缓存详解

    目录 一级缓存 一级缓存的组织 一级缓存的生命周期 一级缓存的工作流程 Cache接口的设计以及CacheKey的定义 一级缓存的性能分析 一级缓存与Spring 事务一级缓存存在的弊端 官方文档分析 Spring通过Mybatis调用数据
  • Servlet 三角形判断以及面积计算

    题目描述 xff1a 用html和servlet编程实现输入三角形的三个边长并计算和输出三角形的面积 要求如下 1 编写一个inputhtml页面 xff0c 页面中包括输入三个边长和和提交按钮的表单 2 编写一个文件名为TriangleS
  • Warning: Stopping docker.service, but it can still be activated by: docker.socket解决方案

    文章目录 问题描述 xff1a 1 解决方案一2 解决方案二 xff1a 问题描述 xff1a 当容器开启自动启动时 xff0c 我们想要关闭docker的时候发现会出现 xff1a Warning Stopping docker serv
  • 虚拟机Ubuntu安装vs code操作步骤

    1 在浏览器上搜索 xff1a https code visualstudio com Download 2 选择 deb 按钮下载 3 下载完成后打开文件 4 右键安装包 xff0c 选择打开方式 xff1a 软件安装 点击安装 xff0
  • ping不通Linux服务器的原因?

    ping命令是各种操作系统中经常会用到的一个网络命令 xff0c 也是一个通信协议 xff0c 主要用来测试目标主机的连通性 xff0c 检查网络是否连通 问题 xff1a 那ping不通Linux系统服务器是什么原因呢 xff1f 总结
  • RHCE第二天

    作业 xff1a 1 配置chrony时间服务器 xff0c 确保客户端主机能和服务主机同步时间 两台机器 第一台机器作为时间服务器从ntp aliyun com同步时间 xff08 注意包含意外情况 xff0c 如果不能上外网 xff0c
  • ubuntu20.04版本 安装ros1与px4、mavros、QGroundControl

    基于个人安装时的操作以及所浏览的链接 xff0c 仅供参考 文章目录 前言一 pandas是什么 xff1f 二 使用步骤 1 引入库2 读入数据总结 前言 使用ubuntu下载ros px4似乎是一件十分繁琐以及困难的事情 xff0c 但
  • 无用的知识--定时提醒(go语言小工具)

    遇到喜欢的事情总是欲罢不能 xff0c 一不小心就酿成了打错 xff0c 比如说在B站上学习 xff08 卷 xff09 过度 xff0c 错过了重要的事情 不用担心 xff0c 今天分享go语言写一个windows系统中定时提醒小工具 p
  • 重装Office后打开Powerpoint和excel提示找不到VCRUNTIME140_1.dll的解决办法(亲测成功,简单有效)

    1 下载VCRUNTIME140 1 dll xff08 可搜索下载途径 xff09 2 将其复制到OFFICE安装目录 xff0c 如下 C Program Files Microsoft Office16 3 再次打开即成功 xff01
  • ERROR:zygote_host_。。。。。Running as root without --no-sandbox is not supported.

    安装好google后 xff0c 在命令行输入google chrome后出现 xff0c ERROR zygote host impl linux cc 89 Running as root without no sandbox is n
  • 【IOT开发】蓝牙模块与PC连接通讯实验

    这是在一个项目中 xff0c 需要开发 windows APP xff0c 通过蓝牙与下位机通讯 之前接触过的一些蓝牙项目 xff0c 大多是 模块与模块 通讯 xff0c 也见过很多模块 手机通讯的教程 xff0c 但PC端直接与蓝牙模块
  • Linux安装JDK详细教程(附图)

    Linux安装JDK详细教程 xff08 图文教程 xff09 这里介绍两种方式 xff1a yum安装方式和手动安装 1 yum安装 1 1 查看JDK版本 xff0c 找到你想要安装的JDK版本 xff0c 这里以 JDK1 8 为例
  • AD布线后批量改线宽

    最近在学习AD画板 xff0c 打算布线结束后再改线宽 xff0c 遇到了一些问题 xff0c 经过网上的资料已经解决 首先 xff0c 右键空白处 xff0c 选择第一个 查找相似对象 然后用十字标选择想要更改的线 在弹出的框中更改 NE
  • 使用springboot启动类报错: 找不到或无法加载主类怎么解决?

    出现问题的原因是 xff1a 在使用springboot启动类时 xff0c 并没有写错代码和注解 xff0c 然后它还是报错找不或无法加载主类 解决此问题的办法 就是 xff0c 重新在项目结构中的Modules吧项目移除再次加载进了即可
  • 【iOS】---pthread,NSThread

    在iOS中多线程开发有四种方式 xff0c 在之前我们浅浅了解了一下GCD xff0c 这期来看看pthread和NSThread pehread pthread简介 pthread 是一套通用的多线程的 API xff0c 可以在Unix