swift Concurrent 异步编程

Swift 5.5 新特性

class Numbers {
    let info = Info()
    
    func getNum() async -> Int {
        
        let time = UInt64.random(in: 2...4)
        
        print("延时:\(time): ", Thread.current)
        
        return await random(time)
    }
    
    func getThrowNum() async throws -> Int {
        
        let time = UInt64.random(in: 2...4)
        
        print("延时:\(time): ", Thread.current)
        
        if time == 4 {
            throw NSError(domain: "4秒", code: 100)
        }
        return await random(time)
    }
    
    func random(_ time: UInt64) async -> Int {
        try? await Task.sleep(nanoseconds: time * 1_000_000_000)
        return Int.random(in: 0...100)
    }
}

异步串行

func serial() async {
    let numbers = Numbers()
    
    var beginDate = Date()
    print(Thread.current)
    
    let num1 = await numbers.getNum()
    
    print(num1, " ", beginDate.distance(to: Date()))
    beginDate = Date()
    
    let num2 = await numbers.getNum()
    
    print(num2, " ", Date().timeIntervalSince(beginDate))
}

<_NSMainThread: 0x600000e48700>{number = 1, name = main}
延时:2: <_NSMainThread: 0x600000e48700>{number = 1, name = main}
20 2.001320004463196
延时:4: <_NSMainThread: 0x600000e48700>{number = 1, name = main}
88 4.379878997802734

异步并发

func concurrent() async {
    let numbers = Numbers()
    
    async let num1 = numbers.getNum()
    async let num2 = numbers.getNum()
                
    print(Thread.current)
    
    let beginDate = Date()
    
    let nums = await [num1, num2]
    
    print(Date().timeIntervalSince(beginDate))
    
    print(nums)
}

<_NSMainThread: 0x6000002907c0>{number = 1, name = main}
延时:4: {number = 6, name = (null)}
延时:3: {number = 6, name = (null)}
4.377479910850525
[90, 32]

TaskGroup

func group() async {
    let begin = Date()
    
    let results = await withTaskGroup(of: Int.self) { taskGroup -> [Int] in
        
        for _ in 0..<4 {
            taskGroup.addTask {
                let nums = Numbers()
                return await nums.getNum()
            }
        }
        
        var results = [Int]()
        
        for await result in taskGroup {
            results.append(result)
        }
        return results
    }
    
    print(begin.distance(to: Date()))
    print(results)
}

延时:4: {number = 7, name = (null)}
延时:3: {number = 7, name = (null)}
延时:3: {number = 7, name = (null)}
延时:4: {number = 7, name = (null)}
4.001741886138916
[55, 89, 60, 46]

func throwGroup() async throws {
    let begin = Date()
    
    let results = try await withThrowingTaskGroup(of: Int.self, body: {
taskGroup -> [Int] in
        for _ in 0..<4 {
            taskGroup.addTask {
                let nums = Numbers()
                return try await nums.getThrowNum()
            }
        }
        var results = [Int]()
        
        for try await result in taskGroup {
            results.append(result)
        }
        return results
    })
    print(begin.distance(to: Date()))
    print(results)
}

延时:4: {number = 7, name = (null)}
延时:4: {number = 7, name = (null)}
延时:3: {number = 7, name = (null)}
延时:2: {number = 7, name = (null)}
Error Domain=4秒 Code=100 "(null)"

Actor

actor Info {
    var age: Int = 0
    
    func setAge(_ age: Int) {
        self.age = age
    }
}

func setInfo() async {
    let num = await getNum()
    await info.setAge(await getNum())
    await print(info.age)
}

actor无法直接使用set方法,Error:Actor-isolated property 'age' can not be mutated from a non-isolated context

@MainActor
var age: Int = 0

func setInfo() async {
    let num = await getNum()
            
    await MainActor.run {
        age = num
    }
    await print(age)
}

Result

extension Result where Failure == Error {
    init(operation: @escaping @Sendable () async throws -> Success) async {
        do {
            let success = try await operation()
            self.init(catching: { success })
        } catch let err {
            self.init(catching: { throw err })
        }
    }
}

Resultasync的结合:

@Sendable
func throwGroup() async throws {
    let begin = Date()
    
    let results = try await withThrowingTaskGroup(of: Int.self, body: { taskGroup -> [Int] in
        for _ in 0..<4 {
            taskGroup.addTask {
                let nums = Numbers()
                return try await nums.getThrowNum()
            }
        }
        var results = [Int]()
        
        for try await result in taskGroup {
            results.append(result)
        }
        return results
    })
    print(begin.distance(to: Date()))
    print(results)
}

let result = await Result(operation: throwGroup)
print(result)

延时:2: {number = 5, name = (null)}
延时:2: {number = 5, name = (null)}
延时:3: {number = 5, name = (null)}
延时:2: {number = 5, name = (null)}
3.001500964164734
[26, 34, 67, 62]
success()

你可能感兴趣的:(swift Concurrent 异步编程)