百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Swift-多线程(@transactional 多线程)

bigegpt 2025-04-07 12:14 13 浏览

摘要

本文不探讨子线程、主线程、同步和异步的常规操作。只是使用DispatchWorkItem 属性来处理1.子线程切换到主线程和2.主动停止正在进行的线程这两种场景,提供一些不同的实现思路。

DispatchWorkItem还可以有其他的场景的应用,这次仅仅做个抛砖引玉。

应用场景

多线程主要的应用场景是:

  1. 子线程加载耗时操作,比如网络请求
  2. 延时操作
  3. 加锁处理

API 及语言

DispatchObject

Swift

核心逻辑/代码

swift 中的多线程处理主要用DispatchQueue的函数。可以创建或者切换到其他线程;也可以设置async(异步)和sync(同步)状态。

这里不再介绍常规操作,主要介绍使用DispatchWorkItem封装多线程函数,并可以自定义处理事件,比如停止多线程任务等。

DispatchWorkItem:A DispatchWorkItem encapsulates work to be performed on a dispatch queue or within a dispatch group. You can also use a work item as a DispatchSource event, registration, or cancellation handler.(DispatchWorkItem封装了要在调度队列或调度组中执行的工作。您还可以将工作项用作DispatchSource事件、注册或取消处理程序)

封装中的主要功能:

  • 子线程处理完成后切换到主线程
// 创建 workItem
let item = DispatchWorkItem(block: task)
// 子线程异步处理 workItem
DispatchQueue.global().async(execute: item)
// item 调用 notify 通知到主线程处理事件
item.notify(queue: DispatchQueue.main, execute: main)
  • 异步延时处理,在延时的过程中,可以主动触发中断延时之后的处理
// 封装延时操作方法
@discardableResult
private static func _asyncDelay(_ seconds: Double,
                                _ task: @escaping Task,
                                _ mainTask: Task? = nil) -> DispatchWorkItem {
    let item = DispatchWorkItem(block: task)
    DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
    if let main = mainTask {
        item.notify(queue: DispatchQueue.main, execute: main)
    }
    return item
}
// 实现 item 方法
let item = Async.asyncDelay(2) {
    print("2 秒后处理事件")
}

// 主动关闭
item.cancel()

多线程 - once

dispatch_once 在 Swift 中已被废弃,可以用类型属性或者全局变量/常量来达到lazy + dispatch_once 效果

fileprivate let initTask2: Void = { print("initTask2")}()
class Data {
    static let initTask1: Void = {
        print("initTask1")
    }()
    
    init() {
        // 该方法只会被实现一次
        let _ = Self.initTask1
        let _ = initTask2
    }
}

示例代码

// MARK: - 多线程自定义封装
struct Async {
    typealias Task = () -> Void
    
    // MARK: - 异步处理事件
    static func async(_ task: @escaping Task) {
        _async(task)
    }
    
    static func async(_ task: @escaping Task,
                      _ mainTask: @escaping Task) {
        _async(task, mainTask)
    }
    
    private static func _async(_ task: @escaping Task,
                               _ mainTask: Task? = nil) {
        let item = DispatchWorkItem(block: task)
        DispatchQueue.global().async(execute: item)
        if let main = mainTask {
            item.notify(queue: DispatchQueue.main, execute: main)
        }
    }
    
    // MARK: - 延时处理事件
    @discardableResult
    static func asyncDelay(_ seconds: Double,
                           _ task: @escaping Task) -> DispatchWorkItem {
        return _asyncDelay(seconds, task)
    }
    
    @discardableResult
    static func asyncDelay(_ seconds: Double,
                           _ task: @escaping Task,
                           _ mainTask: @escaping Task) -> DispatchWorkItem {
        return _asyncDelay(seconds, task, mainTask)
    }
    
    @discardableResult
    private static func _asyncDelay(_ seconds: Double,
                                    _ task: @escaping Task,
                                    _ mainTask: Task? = nil) -> DispatchWorkItem {
        let item = DispatchWorkItem(block: task)
        DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + seconds, execute: item)
        if let main = mainTask {
            item.notify(queue: DispatchQueue.main, execute: main)
        }
        return item
    }
}

相关推荐

Go语言泛型-泛型约束与实践(go1.7泛型)

来源:械说在Go语言中,Go泛型-泛型约束与实践部分主要探讨如何定义和使用泛型约束(Constraints),以及如何在实际开发中利用泛型进行更灵活的编程。以下是详细内容:一、什么是泛型约束?**泛型...

golang总结(golang实战教程)

基础部分Go语言有哪些优势?1简单易学:语法简洁,减少了代码的冗余。高效并发:内置强大的goroutine和channel,使并发编程更加高效且易于管理。内存管理:拥有自动垃圾回收机制,减少内...

Go 官宣:新版 Protobuf API(go pro版本)

原文作者:JoeTsai,DamienNeil和HerbieOng原文链接:https://blog.golang.org/a-new-go-api-for-protocol-buffer...

Golang开发的一些注意事项(一)(golang入门项目)

1.channel关闭后读的问题当channel关闭之后再去读取它,虽然不会引发panic,但会直接得到零值,而且ok的值为false。packagemainimport"...

golang 托盘菜单应用及打开系统默认浏览器

之前看到一个应用,用go语言编写,说是某某程序的windows图形化客户端,体验一下发现只是一个托盘,然后托盘菜单的控制面板功能直接打开本地浏览器访问程序启动的webserver网页完成gui相关功...

golang标准库每日一库之 io/ioutil

一、核心函数概览函数作用描述替代方案(Go1.16+)ioutil.ReadFile(filename)一次性读取整个文件内容(返回[]byte)os.ReadFileioutil.WriteFi...

文件类型更改器——GoLang 中的 CLI 工具

我是如何为一项琐碎的工作任务创建一个简单的工具的,你也可以上周我开始玩GoLang,它是一种由Google制作的类C编译语言,非常轻量和快速,事实上它经常在Techempower的基准测...

Go (Golang) 中的 Channels 简介(golang channel长度和容量)

这篇文章重点介绍Channels(通道)在Go中的工作方式,以及如何在代码中使用它们。在Go中,Channels是一种编程结构,它允许我们在代码的不同部分之间移动数据,通常来自不同的goro...

Golang引入泛型:Go将Interface「」替换为“Any”

现在Go将拥有泛型:Go将Interface{}替换为“Any”,这是一个类型别名:typeany=interface{}这会引入了泛型作好准备,实际上,带有泛型的Go1.18Beta...

一文带你看懂Golang最新特性(golang2.0特性)

作者:腾讯PCG代码委员会经过十余年的迭代,Go语言逐渐成为云计算时代主流的编程语言。下到云计算基础设施,上到微服务,越来越多的流行产品使用Go语言编写。可见其影响力已经非常强大。一、Go语言发展历史...

Go 每日一库之 java 转 go 遇到 Apollo?让 agollo 来平滑迁移

以下文章来源于GoOfficialBlog,作者GoOfficialBlogIntroductionagollo是Apollo的Golang客户端Apollo(阿波罗)是携程框架部门研...

Golang使用grpc详解(golang gcc)

gRPC是Google开源的一种高性能、跨语言的远程过程调用(RPC)框架,它使用ProtocolBuffers作为序列化工具,支持多种编程语言,如C++,Java,Python,Go等。gR...

Etcd服务注册与发现封装实现--golang

服务注册register.gopackageregisterimport("fmt""time"etcd3"github.com/cor...

Golang:将日志以Json格式输出到Kafka

在上一篇文章中我实现了一个支持Debug、Info、Error等多个级别的日志库,并将日志写到了磁盘文件中,代码比较简单,适合练手。有兴趣的可以通过这个链接前往:https://github.com/...

如何从 PHP 过渡到 Golang?(php转golang)

我是PHP开发者,转Go两个月了吧,记录一下使用Golang怎么一步步开发新项目。本着有坑填坑,有错改错的宗旨,从零开始,开始学习。因为我司没有专门的Golang大牛,所以我也只能一步步自己去...