在CTP中,CTP thost会异步发送相关行情和交易回报信息给订阅方或策略管理者(这里简称为strategyManager)。那么,模拟一下CTP的机制,有利于在CTP平台上,构建策略交易支持体系。

一、主要涉及几方面:

1、thost异步发送相关信息

利用多线程,多生产者单消费者模式来模拟发送相关信息,可以选用标准库中的mpsc::channel.

2、策略管理者把相关信息发分给不同的策略

二、方案1: 单channel+单线程

use std::thread;
use std::sync::mpsc::channel;
use std::collections::VecDeque;
use std::time::Duration;
use rand::Rng;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::thread::Thread;
use std::cell::RefCell;# [derive(Debug)]
struct RtnMarketData(String);
# [derive(Debug)]
struct RtnOrder(String);
# [derive(Debug)]
struct RtnTrade(String);//模拟thost传过来的不同的值;
# [derive(Debug)]
enum TradeData{RtnMarketData(String),RtnOrder(String),RtnTrade(String),
}
struct Strategy{stra_name:String,stra_thread_builder:thread::Builder,stra_instructions:Vec<String>,//订阅的相关合约
}
impl Strategy{fn new(name:String,instrs:Vec<String>)->Self{Self{stra_name: name,stra_thread_builder: thread::Builder::new(),stra_instructions:instrs,}}fn OnRtnMarketData(&self,md:&TradeData){println!(" -> strategy:{:?} RtnMarketData=> recv:{:?}",self.stra_name,md);}fn OnRtnOrder(&self,order:&TradeData){println!(" -> strategy:{:?} RtnOrder => recv:{:?}",self.stra_name,order);}fn OnRtnTrade(&self,trade:&TradeData){println!(" -> strategy:{:?} RtnTrade=> recv:{:?}",self.stra_name,trade);}
}
struct StrategyGroup{//stra_list : RefCell<Vec<Strategy>>,stra_list : Vec<Strategy>,
}
impl StrategyGroup{fn new(list:Vec<Strategy>) -> Self{//stra_list:vec![Strategy::new("DSCJ",vec!["IC","IF"]),Strategy::new("WSDJ",vec!["cu,ag"])]Self{//stra_list:RefCell::new(list),stra_list:list,}}
}
struct StrategyManager{thread_builder : thread::Builder,stra_group:StrategyGroup,
}
impl StrategyManager{fn new(group:StrategyGroup)->Self{Self{thread_builder : thread::Builder::new(),stra_group:group,}}
}fn simulate_send(tx:Sender<TradeData>,n_thread:u32){for i in 0..n_thread {let tx = tx.clone();thread::spawn(move||{let mut n = 0;loop{let rand_value:u32 = rand::thread_rng().gen_range(0, 1000);n = n + 1;println!("rand_value:{:?} n:{:?} thread id :{:?}",rand_value,n,i);thread::sleep(Duration::from_millis(300));match rand_value {0...600 => {match rand_value{0...100 => tx.send(TradeData::RtnMarketData("IC".to_string())).unwrap(),100...300=> tx.send(TradeData::RtnMarketData("IF".to_string())).unwrap(),300...400=> tx.send(TradeData::RtnMarketData("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnMarketData("ag".to_string())).unwrap(),}},600...900 => {match rand_value{600...700 =>tx.send(TradeData::RtnOrder("IC".to_string())).unwrap(),700...750 =>tx.send(TradeData::RtnOrder("IF".to_string())).unwrap(),750...800 =>tx.send(TradeData::RtnOrder("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnOrder("ag".to_string())).unwrap(),}},_ => {match rand_value{900...920 =>tx.send(TradeData::RtnTrade("IC".to_string())).unwrap(),920...940 =>tx.send(TradeData::RtnTrade("IF".to_string())).unwrap(),940...960 =>tx.send(TradeData::RtnTrade("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnTrade("ag".to_string())).unwrap(),}}};}});}
}
fn dispatch_data(rx:&Receiver<TradeData>,stra_group:&StrategyGroup){//let (tx,rx) = channel();let strategys = &*stra_group.stra_list;loop{let  ref value = rx.recv().unwrap();match value {TradeData::RtnMarketData(d) =>{for strategy in strategys {if strategy.stra_instructions.contains(&d){strategy.OnRtnMarketData(value);}}},TradeData::RtnOrder(e) =>{for strategy in strategys {if strategy.stra_instructions.contains(&e){strategy.OnRtnOrder(value);}}},TradeData::RtnTrade(f) =>{for strategy in strategys {if strategy.stra_instructions.contains(&f){strategy.OnRtnTrade(value)}}},}}}
fn generate_strategyManager()-> StrategyManager {let strategy_01 =Strategy::new("DSCJ".to_string(),vec!["IC".to_string(),"IF".to_string()]);let strategy_02 =Strategy::new("WSDJ".to_string(),vec!["IF".to_string()]);let strategy_03 =Strategy::new("TTTT".to_string(),vec!["ag".to_string(),"cu".to_string()]);let stra_group = StrategyGroup::new(vec![strategy_01,strategy_02,strategy_03]);StrategyManager::new(stra_group)
}fn main(){//模拟生成相关的策略、策略group、策略管理者let stra_manager = generate_strategyManager();// 模拟thost let (tx,rx) = channel::<TradeData>();//模拟多线程异步进行接收thost相关的行情等信息simulate_send(tx,10);println!("main=>");dispatch_data(&rx,&stra_manager.stra_group);thread::sleep(Duration::from_millis(500000));
}

三、效果图


四、资源占用情况

在去掉了sleep之后,可以看到,内存一直在上升;因为10个线程不断的发行情,这个压力是很大的;策略的分发的速度又来不及,占用的资源会较大。

这个请大家注意!

五、方案2:多channel + 多线程方案

1、这个模拟,并没有模拟订阅thost的机制;
2、子策略并没有专有线程去接收相关信息;现在是strategyManager中单线程进行分发,并负责策略中信号处理。这部分应交给子策略中的专有线程处理。 即处理的链条过长。

下面的代码实现了两层:channel以及多线程轮询交易所的行情等信息,大大提高了交易的效率。

use std::thread;
use std::sync::mpsc::channel;
use std::collections::VecDeque;
use std::time::Duration;
use rand::Rng;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::thread::Thread;
use std::sync::{Arc, Mutex};
use std::marker::Send;
use std::cell::RefCell;# [derive(Debug,Clone)]
struct RtnMarketData(String);
# [derive(Debug,Clone)]
struct RtnOrder(String);
# [derive(Debug,Clone)]
struct RtnTrade(String);# [derive(Debug,Clone)]
enum TradeData{RtnMarketData(String),RtnOrder(String),RtnTrade(String),
}
trait Get_id{fn get_request_id(&self)-> u32;
}struct Strategy{stra_name:String,receiver:Receiver<TradeData>,lock:Arc<Mutex<u32>>,
}
struct StrategyHandler{stra_name: String,stra_instructions: Vec<String>, //订阅的相关合约sender:Sender<TradeData>,
}
impl StrategyHandler{fn new(name:String,instrs:Vec<String>,send:Sender<TradeData>)->Self{Self{stra_name: name,stra_instructions: instrs,sender:send,}}
}impl Strategy{fn new(name:String,recv:Receiver<TradeData>,lock:Arc<Mutex<u32>>)->Self{Self{stra_name:name,receiver:recv,lock:lock,}}fn spawn(self){thread::spawn(move||{loop{let  value = self.receiver.recv().unwrap();match value {TradeData::RtnMarketData(_) =>{self.OnRtnMarketData(value);},TradeData::RtnOrder(_) =>{self.OnRtnOrder(value);},TradeData::RtnTrade(_) =>{self.OnRtnTrade(value);},}};});}fn OnRtnMarketData(&self,md:TradeData){println!(" -> strategy:{:?} RtnMarketData=> recv:{:?}",self.stra_name,md);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 获取唯一ID,策略逻辑在此if rand_value < 400 {println!("触发交易信号:{:?} id:{:?}",rand_value,self.get_request_id());}thread::sleep(Duration::from_millis(rand_value));}fn OnRtnOrder(&self,order:TradeData){println!(" -> strategy:{:?} RtnOrder => recv:{:?}",self.stra_name,order);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 获取唯一IDif rand_value < 10 {println!("触发OnRtnOrder信号:{:?} id:{:?}",rand_value,self.get_request_id());}}fn OnRtnTrade(&self,trade:TradeData){println!(" -> strategy:{:?} RtnTrade=> recv:{:?}",self.stra_name,trade);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 获取唯一IDif rand_value < 300 {println!("触发OnRtnTrade信号:{:?} id:{:?}",rand_value,self.get_request_id());}}
}impl Get_id for Strategy{fn get_request_id(&self)-> u32{let lock = self.lock.clone();let temp = *lock.lock().unwrap();*lock.lock().unwrap()= temp +1 ;println!("request_ID:{:?}",*lock.lock().unwrap());temp+1}
}struct StrategyGroup{stra_list : Vec<Strategy>,
}
impl StrategyGroup{fn new(list:Vec<Strategy>) -> Self{Self{stra_list:list,}}
}
struct StrategyManager{stra_group: StrategyGroup,
}impl StrategyManager{fn new(group: StrategyGroup)->Self{Self{stra_group: group,}}
}fn simulate_send(tx:Sender<TradeData>,n_thread:u32){for i in 0..n_thread {let tx = tx.clone();thread::spawn(move||{let mut n = 0;loop{let rand_value:u32 = rand::thread_rng().gen_range(0, 1000);n = n + 1;println!("thost send info: thread id :{:?} ,次数 {:?} ",i,n);thread::sleep(Duration::from_millis(500));match rand_value {0...600 => {match rand_value{0...100 => tx.send(TradeData::RtnMarketData("IC".to_string())).unwrap(),100...300=> tx.send(TradeData::RtnMarketData("IF".to_string())).unwrap(),300...400=> tx.send(TradeData::RtnMarketData("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnMarketData("ag".to_string())).unwrap(),}},600...900 => {match rand_value{600...700 =>tx.send(TradeData::RtnOrder("IC".to_string())).unwrap(),700...750 =>tx.send(TradeData::RtnOrder("IF".to_string())).unwrap(),750...800 =>tx.send(TradeData::RtnOrder("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnOrder("ag".to_string())).unwrap(),}},_ => {match rand_value{900...920 =>tx.send(TradeData::RtnTrade("IC".to_string())).unwrap(),920...940 =>tx.send(TradeData::RtnTrade("IF".to_string())).unwrap(),940...960 =>tx.send(TradeData::RtnTrade("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnTrade("ag".to_string())).unwrap(),}}};}});}//thost::new(tx).thost_thread_builder.spawn()
}
fn dispatch_data(rx:&Receiver<TradeData>,_handlers: Vec<StrategyHandler>){let handlers = &_handlers;loop{let  ref value = rx.recv().unwrap();match value {TradeData::RtnMarketData(d) =>{for  handler in handlers {if handler.stra_instructions.contains(&d){//strategy.OnRtnMarketData(value)let tx = handler.sender.clone();tx.send(TradeData::RtnMarketData(d.to_string())).unwrap();println!("dispatch:{:?}",d);}}},TradeData::RtnOrder(e) =>{for  handler in handlers {if handler.stra_instructions.contains(&e){let tx = handler.sender.clone();tx.send(TradeData::RtnOrder(e.to_string())).unwrap();println!("dispatch:{:?}",e);}}},TradeData::RtnTrade(f) =>{for  handler in handlers {if handler.stra_instructions.contains(&f){let tx = handler.sender.clone();tx.send(TradeData::RtnTrade(f.to_string())).unwrap();println!("dispatch:{:?}",f);}}},}}
}
fn strategy_init()-> Vec<StrategyHandler> {let (tx_01,rx_01) = channel::<TradeData>();let (tx_02,rx_02) = channel::<TradeData>();let (tx_03,rx_03) = channel::<TradeData>();let id = Arc::new(Mutex::new(0_u32));let stra_handler_01 = StrategyHandler::new("DSCJ".to_string(),vec!["IC".to_string(),"IH".to_string()],tx_01);let strategy_01 = Strategy::new("DSCJ".to_string(),rx_01,id.clone());println!("a");strategy_01.spawn();println!("b");let stra_handler_02 = StrategyHandler::new("TTTT".to_string(),vec!["IC".to_string(),"IF".to_string()],tx_02);let strategy_02 = Strategy::new("TTTT".to_string(),rx_02,id.clone());strategy_02.spawn();let stra_handler_03 = StrategyHandler::new("WSDJ".to_string(),vec!["ag".to_string(),"cu".to_string()],tx_03);let strategy_03 = Strategy::new("WSDJ".to_string(),rx_03,id.clone());strategy_03.spawn();vec![stra_handler_01,stra_handler_02,stra_handler_03]
}
// 等待=>fn main(){//模拟生成相关的策略、策略group、策略管理者let handlers :Vec<StrategyHandler> = strategy_init();//模拟thostlet (tx,rx) = channel::<TradeData>();//模拟N个多线程异步进行接收thost相关的行情等信息simulate_send(tx,2);println!("main=>");dispatch_data(&rx,handlers);thread::sleep(Duration::from_millis(500000));
}

上面的核心是:sender:Sender < TradeData >和 Receiver < TradeData >要分离,否则在启新线程中,就会把策略本身move进行。
上面不仅有多线程和异步接收相关的信息,而且还有同步交易的模拟,在功能上也比较完整。

六、方法3:单channel +多线程方案

当然,用channel很方便,但有没有简单用加锁的方式,来解决这个问题?

有的,但是架构上,仍二个Arc(Mutex< > ) 放在分开的两部分之中。

下面是代码:

use std::thread;
use std::sync::mpsc::channel;
use std::collections::VecDeque;
use std::time::Duration;
use rand::Rng;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::Sender;
use std::thread::Thread;
use std::sync::{Arc, Mutex};
use std::marker::Send;
use std::cell::RefCell;# [derive(Debug,Clone)]
struct RtnMarketData(String);
# [derive(Debug,Clone)]
struct RtnOrder(String);
# [derive(Debug,Clone)]
struct RtnTrade(String);# [derive(Debug,Clone)]
enum TradeData{RtnMarketData(String),RtnOrder(String),RtnTrade(String),
}
trait Get_id{fn get_request_id(&self)-> u32;
}
trait Get_data{fn push_data(&self,td:TradeData);
}
struct Strategy{stra_name:String,stra_instructions: Vec<String>, //订阅的相关合约lock_id:Arc<Mutex<u32>>,lock_data:Arc<Mutex<VecDeque<TradeData>>>,
}
struct Handler{stra_name:String,stra_instructions: Vec<String>, //订阅的相关合约lock_data:Arc<Mutex<VecDeque<TradeData>>>,
}
impl Handler{fn new(name:String,instrs:Vec<String>,lock_data:Arc<Mutex<VecDeque<TradeData>>>)->Self{Self{stra_name:name,stra_instructions: instrs, //订阅的相关合约lock_data:lock_data,}}
}
impl Get_data for Handler{fn push_data(&self,td:TradeData){let s_clone = self.lock_data.clone();if s_clone.is_poisoned(){println!("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ get_data  posion:{:?}",s_clone.is_poisoned());}let mut guard = match s_clone.lock() {Ok(guard) => guard,Err(poisoned) => {println!(" posion!");poisoned.into_inner()},};println!("push_back 成功!:{:?}",td);guard.push_back(td);}
}
impl Strategy{fn new(name:String,instrs:Vec<String>,lock_id:Arc<Mutex<u32>>,lock_data:Arc<Mutex<VecDeque<TradeData>>>)->Self{Self{stra_name:name,stra_instructions: instrs, //订阅的相关合约lock_id: lock_id,lock_data:lock_data,}}fn spawn(self){let lock = self.lock_data.clone();if lock.is_poisoned(){println!("=======================================>  spawn posion:{:?}",lock.is_poisoned());}thread::spawn(move||{loop{let  value = lock.lock().unwrap().pop_back();//.unwrap();//frontprintln!("=> get value:{:?}",value);thread::sleep(Duration::from_millis(100));match value {Some(TradeData::RtnMarketData(d)) =>{self.OnRtnMarketData(TradeData::RtnMarketData(d));},Some(TradeData::RtnOrder(e)) =>{self.OnRtnOrder(TradeData::RtnOrder(e));},Some(TradeData::RtnTrade(f)) =>{self.OnRtnTrade(TradeData::RtnTrade(f));},_ =>{println!("其它数据类型:{:?}",value);continue;},}};});}fn OnRtnMarketData(&self,md:TradeData){println!(" -> strategy:{:?} RtnMarketData=> recv:{:?}",self.stra_name,md);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 交易获取唯一IDif rand_value < 400 {println!("触发交易信号:{:?} id:{:?}",rand_value,self.get_request_id());}thread::sleep(Duration::from_millis(rand_value));}fn OnRtnOrder(&self,order:TradeData){println!(" -> strategy:{:?} RtnOrder => recv:{:?}",self.stra_name,order);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 交易获取唯一IDif rand_value < 10 {println!("触发OnRtnOrder信号:{:?} id:{:?}",rand_value,self.get_request_id());}}fn OnRtnTrade(&self,trade:TradeData){println!(" -> strategy:{:?} RtnTrade=> recv:{:?}",self.stra_name,trade);let rand_value:u64 = rand::thread_rng().gen_range(200,500);// 交易获取唯一IDif rand_value < 300 {println!("触发OnRtnTrade信号:{:?} id:{:?}",rand_value,self.get_request_id());}}
}impl Get_id for Strategy{fn get_request_id(&self)-> u32{let lock = self.lock_id.clone();let temp = *lock.lock().unwrap();*lock.lock().unwrap()= temp +1 ;println!("request_ID:{:?}",*lock.lock().unwrap());temp + 1}
}struct StrategyGroup{stra_list : Vec<Strategy>,
}
impl StrategyGroup{fn new(list:Vec<Strategy>) -> Self{Self{stra_list:list,}}
}
struct StrategyManager{stra_group: StrategyGroup,
}impl StrategyManager{fn new(group: StrategyGroup)->Self{Self{stra_group: group,}}
}fn simulate_send(tx:Sender<TradeData>,n_thread:u32){for i in 0..n_thread {let tx = tx.clone();thread::spawn(move||{let mut n = 0;loop{let rand_value:u32 = rand::thread_rng().gen_range(0, 1000);n = n + 1;println!("thost send info: thread id :{:?} ,次数 {:?} ",i,n);thread::sleep(Duration::from_millis(50));match rand_value {0...600 => {match rand_value{0...100 => tx.send(TradeData::RtnMarketData("IC".to_string())).unwrap(),100...300=> tx.send(TradeData::RtnMarketData("IF".to_string())).unwrap(),300...400=> tx.send(TradeData::RtnMarketData("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnMarketData("ag".to_string())).unwrap(),}},600...900 => {match rand_value{600...700 =>tx.send(TradeData::RtnOrder("IC".to_string())).unwrap(),700...750 =>tx.send(TradeData::RtnOrder("IF".to_string())).unwrap(),750...800 =>tx.send(TradeData::RtnOrder("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnOrder("ag".to_string())).unwrap(),}},_ => {match rand_value{900...920 =>tx.send(TradeData::RtnTrade("IC".to_string())).unwrap(),920...940 =>tx.send(TradeData::RtnTrade("IF".to_string())).unwrap(),940...960 =>tx.send(TradeData::RtnTrade("cu".to_string())).unwrap(),_ =>tx.send(TradeData::RtnTrade("ag".to_string())).unwrap(),}}};}});}//thost::new(tx).thost_thread_builder.spawn()
}
fn dispatch_data(rx:&Receiver<TradeData>,ss: Vec<Handler>){let ss = &ss;loop{let  ref value = rx.recv().unwrap();match value {TradeData::RtnMarketData(d) =>{for  s in ss {if s.stra_instructions.contains(&d){println!("dispatch 2:{:?}",d);s.push_data(TradeData::RtnMarketData(d.to_string()));}}},TradeData::RtnOrder(e) =>{for  s in ss {if s.stra_instructions.contains(&e){println!("dispatch 4:{:?}",e);s.push_data(TradeData::RtnOrder(e.to_string()));}}},TradeData::RtnTrade(f) =>{for  s in ss {if s.stra_instructions.contains(&f){println!("dispatch 6:{:?}",f);s.push_data(TradeData::RtnTrade(f.to_string()));}}},}}
}
fn strategy_init()-> Vec<Handler> {let id = Arc::new(Mutex::new(0_u32));let v_01 :VecDeque<TradeData> = VecDeque::new();let data_01 = Arc::new(Mutex::new(v_01));let v_02 :VecDeque<TradeData> = VecDeque::new();let data_02 = Arc::new(Mutex::new(v_02));let v_03 :VecDeque<TradeData> = VecDeque::new();let data_03 = Arc::new(Mutex::new(v_03));let handler_01 = Handler::new("DSCJ".to_string(),vec!["IC".to_string(),"IF".to_string()],data_01.clone());let strategy_01 = Strategy::new("DSCJ".to_string(),vec!["IC".to_string(),"IF".to_string()],id.clone(),data_01.clone());strategy_01.spawn();let handler_02 = Handler::new("TTTT".to_string(),vec!["IC".to_string(),"IH".to_string()],data_02.clone());let strategy_02 = Strategy::new("TTTT".to_string(),vec!["IC".to_string(),"IH".to_string()],id.clone(),data_02.clone());strategy_02.spawn();let handler_03 = Handler::new("WSDJ".to_string(),vec!["cu".to_string(),"ag".to_string()],data_03.clone());let strategy_03 = Strategy::new("WSDJ".to_string(),vec!["cu".to_string(),"ag".to_string()],id.clone(),data_03.clone());strategy_03.spawn();vec![handler_01,handler_02,handler_03]
}fn main(){//模拟生成相关的策略、策略group、策略管理者let handlers :Vec<Handler> = strategy_init();//模拟thostlet (tx,rx) = channel::<TradeData>();//模拟N个多线程异步进行接收thost相关的行情等信息simulate_send(tx,2);println!("main=>");dispatch_data(&rx,handlers);thread::sleep(Duration::from_millis(500000));
}

Rust : channel、多线程与 CTP相关机制的模拟相关推荐

  1. android串口补位,Rust多线程中的消息传递机制

    代码说话. use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() { let (tx, rx) = mpsc ...

  2. Java多线程与并发相关 — 原理

    Java多线程与并发相关 - 原理 一 synchronized同步 1. 线程安全问题的主要诱因? 存在共享资源(也称临界资源); 存在多条线程共同操作这些共享数据; 2. 解决办法. 同一时刻有且 ...

  3. python多线程读取数据库数据_Python基于多线程操作数据库相关知识点详解

    Python基于多线程操作数据库相关问题分析 本文实例分析了Python多线程操作数据库相关问题.分享给大家供大家参考,具体如下: python多线程并发操作数据库,会存在链接数据库超时.数据库连接丢 ...

  4. 多线程的等待唤醒机制

    一把锁一把钥匙..就是等待跟唤醒要在同一锁内 /* 多线程的等待唤醒机制 wait(); noyify();*/ class Pes {String name;String sex;boolean f ...

  5. java多线程的底层实现_多线程的底层实现机制 - 欢迎来到古怪匹诺曹的开发世界 - OSCHINA - 中文开源技术交流社区...

    1.多线程的底层实现 (1)首先回答什么是线程 1个进程要想执行任务,必须得有线程.线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行 (2)什么是多线程 1个进程中可以开启多条线程, ...

  6. centos7.1 修改selinux相关机制后出现开机失败,报错faild to load selinux policy  freezing

    1.修改selinux相关机制后出现开机失败,报错faild to load selinux policy  freezing 开机后按E键 进入下界面 在高亮出添加enforcing=0或者seli ...

  7. AutoSAR系列讲解(实践篇)9.4-通信相关机制(下)

    AutoSAR系列讲解(实践篇)9.4-通信相关机制(下) 通信相关机制(下) 一.Deadline Monitoring 1.超时监控 2.超时处理 二.Invalidation 1.失效机制 2. ...

  8. Java 多线程 不使用锁机制 实现交替打印数字和字母

    Java 多线程 不使用锁机制 实现交替打印数字和字母 这是一道经典的面试题,使用两个线程去交替打印数字和字母,输出1A2B3C4D5E6F7G-这样的效果,看了网上很多的文章,基本都是使用Condi ...

  9. 5天不再惧怕多线程——第二天 锁机制

    5天不再惧怕多线程--第二天 锁机制 当多个线程在并发的时候,难免会碰到相互冲突的事情,比如最经典的ATM机的问题,并发不可怕,可怕的是我们没有能力控制. 线程以我的理解可以分为三种 ① 锁. ② 互 ...

  10. Java多线程之线程同步机制(锁,线程池等等)

    Java多线程之线程同步机制 一.概念 1.并发 2.起因 3.缺点 二.三大不安全案例 1.样例一(模拟买票场景) 2.样例二(模拟取钱场景) 3.样例三(模拟集合) 三.同步方法及同步块 1.同步 ...

最新文章

  1. 5G时代,微软又走对了一步棋!
  2. Linux┊详解udev
  3. .NET 5 和 C#9 /F#5 一起到来, 向实现 .NET 统一迈出了一大步
  4. android richtext显示html,【报Bug】关于rich-text显示html 的问题
  5. 新手指南:X5Cloud云端应用安装步骤(有图有说明)
  6. Atitit it领域知识点 划分 acm18知识树 目录 1. Acm总结的18个计算机科学关键领域 ACM知识树 1 1.1. 大学级别的计算机科学知识可以归纳成14个知识领域: 3 2. U
  7. 亲测好用的Topaz AI图像降噪软件:DeNoise AI mac版(支持m1)
  8. 简单整理一下以英文字母命名或者开头的语言
  9. laravel admin里百度编辑器自定义路径和文件名
  10. 区块链三种网络地址btc\eth\fil
  11. 《算法帝国》第一章第二章读书笔记
  12. 第8章 中医证型关联规则挖掘代码调整
  13. 华为cpe虚拟服务器,你真的看懂它了吗?华为5G CPE Pro深度体验
  14. 1核2G3M,系统盘40G,流量500G/月,83一年
  15. 4. js移动端点触(tap)事件
  16. Google搜索设置在新标签页打开的方法
  17. svchost.exe占用cpu100 的解决方法
  18. 【GlobalMapper精品教程】034:创建漫游动画并制作漫游视频的方法
  19. 互联网摸鱼日报(2022-10-20)
  20. H5+CSS3 实现div垂直水平居中的几种方式

热门文章

  1. 手机 物理分辨率 逻辑分辨率
  2. 使用salt-ssh批量管理主机
  3. Crystal Report在.net中的两种显示方式
  4. hadoop集群全纪录
  5. Visual Leak Detector 2.2.3 Visual C++内存检测工具
  6. VS2010打开就自动关闭问题解决
  7. wordpress中文主题problog1.0发布,主打简洁,商务
  8. Maven - 配置setting.xml
  9. Vue生命周期学习总结
  10. ADO.NET五大对象详解(转)