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

个人开发微信小程序讯展网站优化推广

个人开发微信小程序,讯展网站优化推广,广州注册公司流程,建设工程合同的性质是文章目录 一、简介二、创建线程1.创建一个线程2.创建多个线程生成随机数尝试让程序睡一会儿引入多线程 三、线程返回值的处理1.每个线程处理一个独立的值2.多个线程处理一个值Arc(原子引用计数)Mutex(互斥锁)RwLock(读…

文章目录

  • 一、简介
  • 二、创建线程
    • 1.创建一个线程
    • 2.创建多个线程
      • 生成随机数
      • 尝试让程序睡一会儿
      • 引入多线程
  • 三、线程返回值的处理
    • 1.每个线程处理一个独立的值
    • 2.多个线程处理一个值
      • Arc(原子引用计数)
      • Mutex(互斥锁)
      • RwLock(读写锁)


一、简介

多线程 是一种并发执行的技术,它允许一个程序或进程同时执行多个线程。每个线程都是程序执行的一个独立路径,它们可以并行运行,共享进程的资源(如内存空间),但每个线程有自己的指令指针、堆栈和局部变量。多线程的主要目的是提高程序的执行效率,通过同时执行多个任务来充分利用计算机的多核处理器。

  • 在Rust语言中,多线程编程是通过标准库中的std::thread模块来实现的。Rust提供了创建和管理线程的API,以及用于线程间同步和通信的机制,如互斥锁(Mutex)和通道(Channel)。

二、创建线程

1.创建一个线程

use std::thread;  fn main() {  // 创建一个新线程  let handle = thread::spawn(|| {  // 在新线程中执行的代码  println!("Hello from a new thread!");  });  // 等待线程结束  handle.join().unwrap();  
}

2.创建多个线程

use std::thread;  fn main() {  // 创建一个向量来存储线程的句柄  let mut threads = vec![];  // 创建多个线程  for i in 0..5 {  // 使用闭包捕获变量i的值  let thread_number = i;  let handle = thread::spawn(move || {  // 在新线程中打印线程编号  println!("线程 {} 正在运行", thread_number);  });  // 将线程句柄添加到向量中  threads.push(handle);  }  // 等待所有线程完成  for handle in threads {  handle.join().unwrap();  }  // 在主线程中打印一些信息  for i in 0..5 {  println!("主线程打印数字: {}", i);  }  
}# 输出结果:
线程 0 正在运行
线程 1 正在运行
线程 2 正在运行
线程 3 正在运行
线程 4 正在运行
主线程打印数字: 0
主线程打印数字: 1
主线程打印数字: 2
主线程打印数字: 3
主线程打印数字: 4
  • 从输出结果上看,仍然像是顺序执行,所以这里引入一个休眠,让线程执行的时候随机休眠0-3秒。

生成随机数

由于Rust核心语言中没有随机数生成的函数,需要使用rand库来进行

# 首先需要在Cargo.toml中添加以下内容
[dependencies]  
rand = "0.8"# 然后在代码中用use 引入
use rand::Rng;  
use rand::thread_rng;  fn main() {  let mut rng = thread_rng();  for _i in 0..10{let random_number = rng.gen_range(1..4);  println!("随机数是: {}", random_number);  }
}
# 结果:
随机数是: 3
随机数是: 1
随机数是: 3
随机数是: 1
随机数是: 3
随机数是: 1
随机数是: 3
随机数是: 2
随机数是: 3
随机数是: 1

随机数生成的区间与循环一样,是一个前闭后开的区间

尝试让程序睡一会儿

use rand::Rng;  
use std::{thread::sleep, time::Duration};  fn main() {  // 创建一个随机数生成器  let mut rng = rand::thread_rng();  // 生成一个0到3之间的随机秒数  let random_seconds: u64 = rng.gen_range(0..4);  // 将秒数转换为Duration  let duration = Duration::from_secs(random_seconds);  // 让当前线程睡眠指定的时间  sleep(duration);  // 之后的代码会在等待后执行  println!("等待了 {} 秒", random_seconds);  
}

引入多线程

use rand::Rng;  
use std::{thread::sleep, time::Duration};  
use std::thread;  fn main() {  // 创建一个向量来存储线程的句柄  let mut threads = vec![];  // 创建多个线程  for i in 1..=10 {  // 使用闭包捕获变量i的值  let thread_number = i;  let handle = thread::spawn(move || {  // 在新线程中打印线程编号  println!("线程 {} 正在运行", thread_number);      // 创建一个随机数生成器  let mut rng = rand::thread_rng();  // 生成一个0到3之间的随机秒数  let random_seconds: u64 = rng.gen_range(0..4);  // 将秒数转换为Duration  let duration = Duration::from_secs(random_seconds);  // 让当前线程睡眠指定的时间  sleep(duration);  println!("线程 {} 运行结束,休息了{}秒.", thread_number,random_seconds);  });  // 将线程句柄添加到向量中  threads.push(handle);  }  // 等待所有线程完成  for handle in threads {  handle.join().unwrap();  }  // 在主线程中打印一些信息  for i in 0..5 {  println!("主线程打印数字: {}", i);  }  
}# 输出结果
线程 3 正在运行
线程 2 正在运行
线程 5 正在运行
线程 7 正在运行
线程 7 运行结束,休息了0.
线程 4 正在运行
线程 6 正在运行
线程 1 正在运行
线程 8 正在运行
线程 9 正在运行
线程 10 正在运行
线程 6 运行结束,休息了1.
线程 4 运行结束,休息了1.
线程 3 运行结束,休息了1.
线程 9 运行结束,休息了1.
线程 1 运行结束,休息了2.
线程 10 运行结束,休息了2.
线程 5 运行结束,休息了2.
线程 2 运行结束,休息了3.
线程 8 运行结束,休息了3.
主线程打印数字: 0
主线程打印数字: 1
主线程打印数字: 2
主线程打印数字: 3
主线程打印数字: 4

三、线程返回值的处理

对于有返回值的多线程来说有两种情况,一种是每个线程处理一个独立的值,用向量接收,另一种是多个线程处理一个值。

1.每个线程处理一个独立的值

use std::thread;  fn main() {  let mut handles = vec![];  for i in 0..5 {  let handle = thread::spawn(move || {  return i*i;});  handles.push(handle);  }  let mut results = vec![];  for handle in handles {  match handle.join() {  Ok(value) => results.push(value),  Err(e) => println!("Thread panicked: {:?}", e),  }  }  println!("Results: {:?}", results);  //Results: [0, 1, 4, 9, 16]
}

2.多个线程处理一个值

由于多个线程处理一个值,可能造成条件竞争,属于线程不安全行为,Rust语言中提供了3种处理行为。

  • Arc 只读访问,用于共享只读数据,通过原子引用计数管理生命周期。
  • Mutex 互斥锁,用于保护数据,确保一次只有一个线程可以访问数据(提供独占访问)。
  • RwLock 读写锁,用于保护数据,但允许多个读者同时访问,写者必须独占访问。

Arc(原子引用计数)

Arc是一个提供共享所有权的智能指针。它用于在多个所有者之间共享数据,且只允许对这些数据进行只读访问。Arc通过原子操作维护一个引用计数,确保数据的生命周期至少与最长的所有者一样长。当最后一个Arc指针被丢弃时,其指向的数据也会被释放。

use std::sync::Arc;  
use std::thread;  fn main() {  // 创建一个要在多个线程之间共享的值  let data = Arc::new(vec![1, 2, 3, 4, 5]);  // 创建一个向量来存储线程的句柄  let mut handles = vec![];  println!("Thread {:?} is reading value: {:?}", thread::current().id(), &data); // 主线程的线程ID为 1// 创建几个线程来只读访问数据  for _i in 0..data.len() {  let data = data.clone(); // 克隆Arc以便在线程中使用  let handle = thread::spawn(move || {  // 获取Vec的引用以便索引  // 使用 {:?} 来打印 ThreadId  println!("Thread {:?} is reading value: {:?}", thread::current().id(), &data);  });  handles.push(handle);  }  // 等待所有线程完成  for handle in handles {  handle.join().unwrap();  }  
}
# 运行结果
Thread ThreadId(1) is reading value: [1, 2, 3, 4, 5]
Thread ThreadId(2) is reading value: [1, 2, 3, 4, 5]
Thread ThreadId(3) is reading value: [1, 2, 3, 4, 5]
Thread ThreadId(4) is reading value: [1, 2, 3, 4, 5]
Thread ThreadId(5) is reading value: [1, 2, 3, 4, 5]
Thread ThreadId(6) is reading value: [1, 2, 3, 4, 5]

Mutex(互斥锁)

Mutex是一个提供互斥访问的智能指针。它用于保护数据,确保一次只有一个线程能够访问数据。当一个线程拥有Mutex的锁时,其他尝试获取锁的线程将被阻塞,直到锁被释放。

use std::sync::{Arc, Mutex};  
use std::thread;  fn main() {  // 创建一个Arc包裹的互斥锁和值  let counter = Arc::new(Mutex::new(1));  let mut handles = vec![];  // 创建几个线程来增加计数器  for i in 1..10 {  // 克隆Arc智能指针,而不是Mutex或它的值  let counter = Arc::clone(&counter);  let handle = thread::spawn(move || {  // 获取互斥锁以便修改值  let mut num = counter.lock().unwrap();  *num *=i;});  handles.push(handle);  }  // 等待所有线程完成  for handle in handles {  handle.join().unwrap();  }  // 输出最终计数器的值  println!("Result: {}", *counter.lock().unwrap());  // Result: 362880
}

RwLock(读写锁)

RwLock是一个提供读写锁定的智能指针。与Mutex不同,RwLock允许多个读者同时访问数据,但写者必须独占锁。当写者拥有锁时,任何尝试获取读锁或写锁的线程都将被阻塞。当没有写者时,可以有多个读者同时访问数据。

use std::sync::{Arc, RwLock};  fn main() {  let data = Arc::new(RwLock::new(0));  let mut handles = vec![];  // 创建多个读线程  for i in 0..5 {  let data = Arc::clone(&data);  let handle = std::thread::spawn(move || {  let num = data.read().unwrap();  println!("Thread {} Reading value: {}", i,*num);  });  handles.push(handle);  }  // 创建一个写线程  let data = Arc::clone(&data);  let handle = std::thread::spawn(move || {  let mut num = data.write().unwrap();  *num += 1;  println!("Writing value: {}", *num);  });  handles.push(handle);  for handle in handles {  handle.join().unwrap();  }  
}
# 第一次执行结果
Thread 0 Reading value: 0
Thread 3 Reading value: 0
Thread 1 Reading value: 0
Thread 4 Reading value: 0
Thread 2 Reading value: 0
Writing value: 1
# 第二次执行结果
Thread 0 Reading value: 0
Thread 3 Reading value: 0
Thread 1 Reading value: 0
Thread 4 Reading value: 0
Thread 2 Reading value: 0
Writing value: 1

这里有一个问题,就是如果写线程最后执行,那么读线程读的都是原始数据,如果写线程先执行,那么读的就是修改后的数据,所以对读写顺序有要求的话应该做好时序的控制

http://www.hkea.cn/news/199628/

相关文章:

  • 东莞市建设公共交易中心网站百度官网首页
  • 如何建立的网站能争钱优化营商环境 助推高质量发展
  • 做百度网站营销型网站建设排名
  • 网站域名被黑国际新闻最新消息战争
  • 苏州网站开发公司济南兴田德润厉害吗网络自动推广软件
  • 广药网站建设试卷株洲最新今日头条
  • 网站建设管理考核办法微信推广平台怎么做
  • 网站新闻模块代码网络推广有哪些常见的推广方法
  • 合肥大型网站如何推广普通话
  • 高端网站制作软件怎么样推广自己的店铺和产品
  • 无障碍浏览网站怎么做关键词seo排名优化推荐
  • wordpress 247seo推广系统
  • 做深圳门户网站起什么名字好泰州seo外包公司
  • 网站视频上传怎么做百度站长平台论坛
  • wordpress农业模板下载小时seo
  • 做网站语言排名2018发帖推广哪个平台好
  • 销氪crmseo入门讲解
  • 蒙阴哪有做淘宝网站的钓鱼网站制作教程
  • 网站如何做导航条下拉菜单怎么做百度网页
  • 网站开发都做什么平台推广精准客源
  • 网站建设共享ip宁波seo搜索引擎优化
  • 学校网站建设必要性搜索引擎排名
  • 哪里有做区块链网站的百度网址大全在哪里找
  • 加盟平台网站怎么做竞价托管多少钱一个月
  • wordpress 微信 代码网站关键词怎么优化排名
  • 网站推广维护考研培训班哪个机构比较好
  • 网站后台生成器人工智能培训班收费标准
  • 在线做app的网站武汉网络营销公司排名
  • 了解深圳网站页面设计潍坊百度关键词优化
  • 制作网站怎样找公司来帮做seo词条