首页 文章 精选 留言 我的

精选列表

搜索[氛围编程],共10003篇文章
优秀的个人博客,低调大师

打造编程环境

Python虚拟环境 下载安装 清华的镜像 [https://mirror.tuna.tsinghua.edu.cn/help/anaconda/] Miniconda 安装包可以到 https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/ 下载。 下载后直接默认安装Miniconda 添加环境变量 下面进入到非常关键的添加环境变量的步骤,无论你是否有选择”Add Anaconda to my PATH environment variable”,都建议按照以下步骤进行环境变量的添加或查看。 Miniconda的安装中第三个步骤时记下的默认安装路径,”新建”三个路径:1)默认路径本身;2)默认路径+”\Scripts”;3)默认路径+”\Library\bin” 例如默认路径为:”C:\Users\Administrator\Miniconda3”,那么需要添加的三个路径则是: 1)C:\Users\Administrator\Miniconda3; 2)C:\Users\Administrator\Miniconda3\Scripts; 3)C:\Users\Administrator\Miniconda3\Library\bin 基本命令 1.Windows最好配合ConEmu使用 工具链接: https://pan.baidu.com/s/1gVybZSQdU27hz0YZf8AWYw 密码: vevt 查看版本 conda info —envs 或 conda env list 注意,为了避免你的网络太慢,请先运行下面命令加速一些** conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/ conda config --set show_channel_urls yes 安装完整版python2版本的conda conda create -n py2 python=2 移除虚拟环境 conda remove --all -n 3todo 创建只有django的python2环境,名字py2-dj10,注意,python=2 django是连续参数 conda create -n py2-dj10 python=2 django=1.10 进入环境 coa test 退出环境 cod 删除虚拟环境 cr test 新建虚拟环境示意图: 自定义命令别名 Windows最好配合ConEmu使用。在settings->Startup>Environment alias cl=conda env list alias cc=conda create -n $ alias coa=activate $ alias cod=deactivate alias cr=conda remove --all -n $* --- 知识在于点滴积累

优秀的个人博客,低调大师

Python串口编程

python的串口网上有很多例子,这里了只是把认为好的整理到一起。 首先,应该安装serial模块,还能开始后续的操作。我用的python2.6,serial模块可以在这里下载安装serial模块下载 1,字符串的发送接收 短接串口的2、3脚,创建一个文本,如: [python] view plaincopy importserial t=serial.Serial('com12',9600) n=t.write('youaremyworld') printt.portstr printn str=t.read(n) printstr [python] view plain copy importserial t=serial.Serial('com12',9600) n=t.write('youaremyworld') printt.portstr printn str=t.read(n) printstr 或者你可以稍微添加几句,变成你任意输入后打印出你的键入信息。 [python] view plaincopy importserial t=serial.Serial('com12',9600) printt.portstr strInput=raw_input('entersomewords:') n=t.write(strInput) printn str=t.read(n) printstr [python] view plain copy importserial t=serial.Serial('com12',9600) printt.portstr strInput=raw_input('entersomewords:') n=t.write(strInput) printn str=t.read(n) printstr 其中,read(value)方法的参数value为需要读取的字符长度。如果想要全部读取,提供两个方法: 1)inWaiting::监测接收字符。inWaitting返回接收字符串的长度值,然后把这个值赋给read做参数。 2)readall()::读取全部字符。 =================================================================================================================================== 2,十六进制显示 十六进制显示的实质是把接收到的字符诸葛转换成其对应的ASCII码,然后将ASCII码值再转换成十六进制数显示出来,这样就可以显示特殊字符了。 在这里定义了一个函数,如hexShow(argv),代码如下: [python] view plaincopy importserial defhexShow(argv): result='' hLen=len(argv) foriinxrange(hLen): hvol=ord(argv[i]) hhex='%02x'%hvol result+=hhex+'' print'hexShow:',result t=serial.Serial('com12',9600) printt.portstr strInput=raw_input('entersomewords:') n=t.write(strInput) printn str=t.read(n) printstr hexShow(str) [python] view plain copy importserial defhexShow(argv): result='' hLen=len(argv) foriinxrange(hLen): hvol=ord(argv[i]) hhex='%02x'%hvol result+=hhex+'' print'hexShow:',result t=serial.Serial('com12',9600) printt.portstr strInput=raw_input('entersomewords:') n=t.write(strInput) printn str=t.read(n) printstr hexShow(str) =================================================================================================================================== 3,十六进制发送 十六进制发送实质是发送十六进制格式的字符串,如'\xaa','\x0b'。重点在于怎么样把一个字符串转换成十六进制的格式,有两个误区: 1)'\x'+'aa'是不可以,涉及到转义符反斜杠 2)'\\x'+'aa'和r'\x'+'aa'也不可以,这样的打印结果虽然是\xaa,但赋给变量的值却是'\\xaa' 这里用到decode函数, [python] view plaincopy list='aabbccddee' hexer=list.decode("hex") printhexer [python] view plain copy list='aabbccddee' hexer=list.decode("hex") printhexer 需要注意一点,如果字符串list的长度为奇数,则decode会报错,可以按照实际情况,用字符串的切片操作,在字符串的开头或结尾加一个'0' 假如在串口助手以十六进制发送字符串"abc",那么你在python中则这样操作“self.l_serial.write(”\x61\x62\x63") ” 当然,还有另外一个方法: [python] view plaincopy strSerial="abc" strHex=binascii.b2a_hex(strSerial) #printstrHex strhex=strHex.decode("hex") #printstrhex self.l_serial.write(strhex); [python] view plain copy strSerial="abc" strHex=binascii.b2a_hex(strSerial) #printstrHex strhex=strHex.decode("hex") #printstrhex self.l_serial.write(strhex); 同样可以达到相同目的。 那么,串口方面的就整理完了。 源代码 额外一个小知识: 索引:也称作是下标操作,那么python就会为你抓取序列中对应位置的项目。它是从0开始计数,那么str[0]即为第一个项目,str[3]为第四个。(str只是一个参考序列)。当然呢,python有点不同是它可以是负数,位置就是从序列尾开始计算的。str[-1]表示序列的最后一个元素,而str[-2]为倒数第二个。 切片操作:顾名思义,就是可以连续一整块,把什么切成几段,但那一段是连续的。它是序列名后跟一个方括号,方括号有一对可选的数字,并用冒号分割。数是可选的,但冒号是必须的。例如str[1:3]返回从位置1开始,包括位置2,但是不包括位置3,返回的是一个含有两个项目的切片。类似,str[:]返回整个序列的拷贝。同样,它也是可以用负数的。

优秀的个人博客,低调大师

Android 网路编程

1、获得网络信息 首先在AndroidManifest.xml中加入权限 <uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" /> Code代码如下: public class MainActivity extends Activity { TextView netWorkTextView; ConnectivityManager cManager; NetworkInfo networkInfo; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); netWorkTextView = (TextView)findViewById(R.id.networkInfo); cManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); } @Override protected void onStart() { super .onStart(); networkInfo = cManager.getActiveNetworkInfo(); netWorkTextView.setText(networkInfo.toString()); } } 显示入下图:代表的意思,采用WIFI连接,其它不解释。 2 .Socket的网络通信 1)服务端: 新建Android工程SocketServerDemo。 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); startService( new Intent( this ,SocketService. class )); } } SocketService类 public class SocketService extends Service{ Thread mServiceThread; Socket client; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null ; } @Override public void onCreate() { super .onCreate(); mServiceThread = new Thread( new SocketServerThread()); } public class SocketServerThread extends Thread { private static final int PORT = 8801 ; private SocketServerThread() { } @Override public void run() { // TODO Auto-generated method stub try { ServerSocket serverSocket = new ServerSocket(PORT); while ( true ) { System.out.println( "begin client connected" ); client = serverSocket.accept(); System.out.println( "client connected" ); BufferedReader reader = new BufferedReader( new InputStreamReader(client.getInputStream())); System.out.println( "read from client:" ); String textLine = reader.readLine(); if (textLine.equalsIgnoreCase( "EXIT" )) { System.out.println( "EXIT invoed, closing client" ); break ; } System.out.println(textLine); PrintWriter writer = new PrintWriter( new BufferedWriter( new OutputStreamWriter(client.getOutputStream()))); writer.println( "ECHO from server: " + textLine); writer.flush(); writer.close(); reader.close(); } } catch (IOException e) { // TODO: handle exception System.err.println(e); } } } } 2)客户端:新建Android工程SocketClientDemo public class MainActivity extends Activity { private static final String SERVERIP = "192.168.1.100" ; //自己电脑的IP private static final int SERVERPORT = 8801 ; TextView mMsgRev; EditText mMsgEdit; Button mMsgSendBtn; String mSendMsg; String mReceivedMsg; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); mMsgRev = (TextView) findViewById(R.id.receive_msg); mMsgEdit = (EditText) findViewById(R.id.edit_msg); mMsgSendBtn = (Button) findViewById(R.id.send_msg); mMsgSendBtn.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Socket socket = null ; mSendMsg = mMsgEdit.getText().toString(); try { socket = new Socket(SERVERIP, SERVERPORT); PrintWriter writer = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream()))); writer.println(mSendMsg); writer.flush(); BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream())); mReceivedMsg = reader.readLine(); if (mReceivedMsg != null ) { mMsgRev.setText(mReceivedMsg); } else { mMsgRev.setText( "receive data error" ); } writer.close(); reader.close(); socket.close(); } catch (UnknownHostException e) { // TODO: handle exception Log.i( "Error" , e.getMessage()); } catch (IOException e) { // TODO: handle exception Log.i( "Error" , e.getMessage()); } } }); } } 其中客户端跑在我的平板上,服务端跑在我的手机上。然后再服务端的文本框中输入文本,点击Send按钮,最后会收到信息。 注意:两个程序的端口号8801都是相同的,客户端的IP地址是我的电脑IP地址,两个程序都要有权限 <uses-permission android:name= "android.permission.INTERNET" ></uses-permission> 参考:基于Socket的网络通信 本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/archive/2013/04/03/2997992.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android socket编程

Socket通常也称做”套接字“,用于描述IP地址和端口,它就是网络通信过程中端点的抽象表示。Java在包java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。 SocketServer类,服务器实现: public class SocketServer { ServerSocket sever; public SocketServer(int port){ try{ sever = new ServerSocket(port); }catch(IOException e){ e.printStackTrace(); } } public void beginListen(){ while(true){ try{ final Socket socket = sever.accept(); new Thread(new Runnable(){ public void run(){ BufferedReader in; try{ in = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8")); PrintWriter out = new PrintWriter(socket.getOutputStream()); while (!socket.isClosed()){ String str; str = in.readLine(); out.println("Hello!world!! " + str); out.flush(); if (str == null || str.equals("end")) break; System.out.println(str); } socket.close(); }catch(IOException e){ e.printStackTrace(); } } }).start(); }catch(IOException e){ e.printStackTrace(); } } } } public class TestSocketServer { public static void main(String[] argvs){ SocketServer server = new SocketServer(12345); server.beginListen(); } } 客户端实现: public class SocketClientDemo extends Activity implements Runnable { private TextView tv_msg = null; private EditText ed_msg = null; private Button btn_send = null; private static final String HOST = "192.168.1.223"; private static final int PORT = 12345; private Socket socket = null; private BufferedReader in = null; private PrintWriter out = null; private String content = ""; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); tv_msg = (TextView) findViewById(R.id.TextView); ed_msg = (EditText) findViewById(R.id.EditText01); btn_send = (Button) findViewById(R.id.Button01); try { socket = new Socket(HOST, PORT); in = new BufferedReader(new InputStreamReader(socket.getInputStream())); out = new PrintWriter(new BufferedWriter(new OutputStreamWriter( socket.getOutputStream())), true); } catch (IOException ex) { ex.printStackTrace(); ShowDialog("login exception" + ex.getMessage()); } btn_send.setOnClickListener(new Button.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String msg = ed_msg.getText().toString(); if (socket.isConnected()) { if (!socket.isOutputShutdown()) { out.println(msg); } } } }); new Thread(SocketDemo.this).start(); } public void run() { try { while (true) { if (socket.isConnected()) { if (!socket.isInputShutdown()) { if ((content = in.readLine()) != null) { content += "\n"; Log.d("socket","socket:"+content); } else { } } } } } catch (Exception e) { e.printStackTrace(); } } } 注意在AndroidManifest.xml中加入对网络的访问权限 <uses-permission android:name="android.permission.INTERNET"></uses-permission> 本文转自xyz_lmn51CTO博客,原文链接:http://blog.51cto.com/xyzlmn/1230758,如需转载请自行联系原作者

优秀的个人博客,低调大师

Flutter 异步编程指南

作者:京东物流王志明 1 Dart 中的事件循环模型 在 App 开发中,经常会遇到处理异步任务的场景,如网络请求、读写文件等。Android、iOS 使用的是多线程,而在 Flutter 中为单线程事件循环,如下图所示 Dart 中有两个任务队列,分别为 microtask 队列和 event 队列,队列中的任务按照先进先出的顺序执行,而 microtask 队列的执行优先级高于 event 队列。在 main 方法执行完毕后,会启动事件循环,首先将 microtask 队列中的任务逐个执行完毕,再去执行 event 队列中的任务,每一个 event 队列中的任务在执行完成后,会再去优先执行 microtask 队列中的任务,如此反复,直到清空所有队列,这个过程就是 Dart 事件循环的处理机制。这种机制可以让我们更简单的处理异步任务,不用担心锁的问题。我们可以很容易的预测任务执行的顺序,但无法准确的预测到事件循环何时会处理到你期望执行的任务。例如创建了一个延时任务,但排在前面的任务结束前是不会处理这个延时任务的,也就说这个任务的等待时间可能会大于指定的延迟时间。 Dart 中的方法一旦开始执行就不会被打断,而 event 队列中的事件还来自于用户输入、IO、定时器、绘制等,这意味着在两个队列中都不适合执行计算量过大的任务,才能保证流畅的 UI 绘制和用户事件的快速响应。而且当一个任务的代码发生异常时,只会打断当前任务,后续任务不受影响,程序更不会退出。从上图还可以看出,将一个任务加入 microtask 队列,可以提高任务优先级,但是一般不建议这么做,除非比较紧急的任务并且计算量不大,因为 UI 绘制和处理用户事件是在 event 事件队列中的,滥用 microtask 队列可能会影响用户体验。 总结下 Dart 事件循环的主要概念: Dart 中有两个队列来执行任务:microtask 队列和 event 队列。 事件循环在 main 方法执行完毕后启动, microtask 队列中的任务会被优先处理。 microtask 队列只处理来自 Dart 内部的任务,event 队列中有来自 Dart 内部的 Future、Timer、isolate message,还有来自系统的用户输入、IO、UI 绘制等外部事件任务。 Dart 中的方法执行不会被打断,因此两个队列中都不适合用来执行计算量大的任务。 一个任务中未被处理的异常只会打断当前任务,后续任务不受影响,程序更不会退出。 1.1 向 microtask 队列中添加任务 可以使用顶层方法 scheduleMicrotask 或者 Future.microtask 方法,如下所示: scheduleMicrotask(() => print('microtask1')); Future.microtask(() => print('microtask2')); 使用 Future.microtask 的优势在于可以在 then 回调中处理任务返回的结果。 1.2 向 event 队列中添加任务 Future(() => print('event task')); 基于以上理论,通过如下代码可以验证 Dart 的事件循环机制: void main() { print('main start'); Future(() => print('event task1')); Future.microtask(() => print('microtask1')); Future(() => print('event task1')); Future.microtask(() => print('microtask2')); print('main stop'); 执行结果: main start main stop microtask1 microtask2 event task1 event task1 通过输出结果可以看到,任务的执行顺序并不是按照编写代码的顺序来的,将任务添加到队列不会立刻执行,而执行顺序也完全符合前面讲的规则,当前 main 方法中的代码执行完毕后,才会去执行队列中的任务,且 microTask 队列的优先级高于 event 队列。 2 Dart 中的异步实现 在 Dart 中通过 Future 来执行异步任务, Future 是对异步任务状态的封装,对任务结果的代理,通过 then 方法可以注册处理任务结果的回调方法。 创建方法 Future 方式: Future() Future.delayed() Future.microtask() Future.sync() 2.1 Future() factory Future(FutureOr<T> computation()) { _Future<T> result = new _Future<T>(); Timer.run(() { try { result._complete(computation()); } catch (e, s) { _completeWithErrorCallback(result, e, s); } }); return result; } 上面是 Future() 的源码,可以看到内部是通过启动一个没有延迟的计时器来添加任务的,实用 try catch 来捕获任务代码中可能出现的异常,我们可以在 catchError 回调中来处理异常。 2.2 Future.delayed() factory Future.delayed(Duration duration, [FutureOr<T> computation()?]) { if (computation == null && !typeAcceptsNull<T>()) { throw ArgumentError.value(null, "computation", "The type parameter is not nullable"); } _Future<T> result = new _Future<T>(); new Timer(duration, () { if (computation == null) { result._complete(null as T); } else { try { result._complete(computation()); } catch (e, s) { _completeWithErrorCallback(result, e, s); } } }); return result; } Future.delayed() 与 Future() 的区别是通过一个延迟的计时器来添加任务。 2.3 Future.microtask() factory Future.microtask(FutureOr<T> computation()) { _Future<T> result = new _Future<T>(); scheduleMicrotask(() { try { result._complete(computation()); } catch (e, s) { _completeWithErrorCallback(result, e, s); } }); return result; } Future.microtask() 是将任务添加到 microtask 队列,通过这种可以很方便通过 then 方法中的回调来处理任务的结果。 2.4 Future.sync() factory Future.sync(FutureOr<T> computation()) { try { var result = computation(); if (result is Future<T>) { return result; } else { // TODO(40014): Remove cast when type promotion works. return new _Future<T>.value(result as dynamic); } } catch (error, stackTrace) { var future = new _Future<T>(); AsyncError? replacement = Zone.current.errorCallback(error, stackTrace); if (replacement != null) { future._asyncCompleteError(replacement.error, replacement.stackTrace); } else { future._asyncCompleteError(error, stackTrace); } return future; } } Future.sync() 中的任务会被立即执行,不会添加到任何队列。 在第一个章节中讲到了可以很容易的预测任务的执行顺序,下面我们通过一个例子来验证: void main() { print('main start'); Future.microtask(() => print('microtask1')); Future.delayed(new Duration(seconds:1), () => print('delayed event')); Future(() => print('event1')); Future(() => print('event2')); Future.microtask(() => print('microtask2')); print('main stop'); } 执行结果: main start main stop microtask1 microtask2 event1 event2 delayed event 因为代码比较简单,通过代码可以很容易的预测到执行结果,下面将复杂度稍微提高。 void main() { print('main start'); Future.microtask(() => print('microtask1')); Future.delayed(new Duration(seconds:1), () => print('delayed event')); Future(() => print('event1')) .then((_) => print('event1 - callback1')) .then((_) => print('event1 - callback2')); Future(() => print('event2')).then((_) { print('event2 - callback1'); return Future(() => print('event4')).then((_) => print('event4 - callback')); }).then((_) { print('event2 - callback2'); Future(() => print('event5')).then((_) => print('event5 - callback')); }).then((_) { print('event2 - callback3'); Future.microtask(() => print('microtask3')); }).then((_) { print('event2 - callback4'); }); Future(() => print('event3')); Future.sync(() => print('sync task')); Future.microtask(() => print('microtask2')).then((_) => print('microtask2 - callbak')); print('main stop'); } 执行结果: main start sync task main stop microtask1 microtask2 microtask2 - callbak event1 event1 - callback1 event1 - callback2 event2 event2 - callback1 event3 event4 event4 - callback event2 - callback2 event2 - callback3 event2 - callback4 microtask3 event5 event5 - callback delayed event 看到结果后你可能会疑惑,为什么 event1、event1 - callback1、event1 - callback2 会连续输出,而 event2 - callback1 输出后为什么是 event3,event5、event5 - callback 为什么会在 microtask3 后输出? 这里我们补充下 then 方法的一些关键知识,理解了这些,上面的输出结果也就很好理解了: then 方法中的回调并不是按照它们注册的顺序来执行。 Future 中的任务执行完毕后会立刻执行 then 方法中的回调,并且回调不会被添加到任何队列中。 如果 Future 中的任务在 then 方法调用之前已经执行完毕了,那么会有一个任务被加入到 microtask 队列中。这个任务执行的就是被传入then 方法中的回调。 2.5 catchError、whenComplete Future(() { throw 'error'; }).then((_) { print('success'); }).catchError((error) { print(error); }).whenComplete(() { print('completed'); }); 输出结果: error completed 通过 catchError 方法注册的回调,可以用来处理任务代码产生的异常。不管 Future 中的任务执行成功与否,whenComplete 方法都会被调用。 2.6 async、await 使用 async、await 能以更简洁的编写异步代码,是 Dart 提供的一个语法糖。使用 async 关键字修饰的方法返回值类型为 Future,在 async 方法内可以使用 await 关键字来修饰异步任务,在方法内部达到同步执行的效果,可以达到简化代码和提高可读性的效果,不过如果想要处理异常,需要实用 try catch 语句来包裹 await 修饰的异步任务。 void main() async { print(await getData()); } Future<int> getData() async { final a = await Future.delayed(Duration(seconds: 1), () => 1); final b = await Future.delayed(Duration(seconds: 1), () => 1); return a + b; } 3 Isolate介绍 前面讲到耗时任务不适合放到 microtask 队列或 event 队列中执行,会导致 UI 卡顿。那么在 Flutter 中有没有既可以执行耗时任务又不影响 UI 绘制呢,其实是有的,前面提到 microtask 队列和 event 队列是在 main isolate 中运行的,而 isolate 是在线程中运行的,那我们开启一个新的 isolate 就可以了,相当于开启一个新的线程,使用多线程的方式来执行任务,Flutter 也为我们提供了相应的 Api。 3.1 compute void main() async { compute<String, String>( getData, 'Alex', ).then((result) { print(result); }); } String getData(String name) { // 模拟耗时3秒 sleep(Duration(seconds: 3)); return 'Hello $name'; } compute 第一个参数是要执行的任务,第二个参数是要向任务发送的消息,需要注意的是第一个参数只支持顶层参数。使用 compute() 可以方便的执行耗时任务,但是滥用的话也会适得其反,因为每次调用,相当于新建一个 isolate。上面的代码执行一个经历了 isolate 的创建以及销毁过程,还有数据的传递会经历两次拷贝,因为 isolate 之间是完全隔离的,不能共享内存,整个过程除去任务本身的执行时间,也会非常的耗时,isolate 的创建也比较消耗内存,创建过多的 isolate 还有 OOM 的风险。这时我们就需要一个更优的解决方案,减少频繁创建销毁 isolate 所带来的消耗,最好是能创建一个类似于线程池的东西,只要提前初始化好,后面就可以随时使用,不用担心会发生前面所讲的问题,这时候 LoadBalancer 就派上用场了 3.2 LoadBalancer // 用来创建 LoadBalancer Future<LoadBalancer> loadBalancerCreator = LoadBalancer.create(2, IsolateRunner.spawn); // 全局可用的 loadBalancer late LoadBalancer loadBalancer; void main() async { // 初始化 LoadBalancer loadBalancer = await loadBalancerCreator; // 使用 LoadBalancer 执行任务 final result = await loadBalancer.run<String, String>(getData, 'Alex'); print(result); } String getData(String name) { // 模拟耗时3秒 sleep(Duration(seconds: 3)); return 'Hello $name'; } 使用 LoadBalancer.create() 方法可以创建出一个 isolate 线程池,能够指定 isolate 的数量,并自动实现了负载均衡。应用启动后在合适的时机将其初始化好,后续就有一个全局可用的 LoadBalancer 了。 4 实用经验 4.1 指定任务的执行顺序 在开发中经常会有需要连续执行异步任务的场景,例如下面的例子,后面的一步任务直接需要以来前面任务的结果,所有任务正常执行完毕才算成功。 void main() async { print(await getData()); } Future<int> getData() { final completer = Completer<int>(); int value = 0; Future(() { return 1; }).then((result1) { value += result1; return Future(() { return 2; }).then((result2) { value += result2; return Future(() { return 3; }).then((result3) { value += result3; completer.complete(value); }); }); }); return completer.future; } 这种方式出现了回调地狱,代码非常难以阅读,实际开发中还会有处理异常的代码,会显得更加臃肿,编写难度也大,显然这种方式是不建议使用的。 4.2 使用 then 的链式调用 void main() async { print(await getData()); } Future<int> getData() { int value = 0; return Future(() => 1).then((result1) { value += result1; return Future(() => 2); }).then((result2) { value += result2; return Future(() => 3); }).then((result3) { value += result3; return value; }); } 回调地狱的问题解决了,代码可读性提高很多。 4.3 使用 async、await void main() async { print(await getData()); } Future<int> getData() async { int value = 0; value += await Future(() => 1); value += await Future(() => 2); value += await Future(() => 3); return value; } 效果显而易见,代码更加清晰了。 4.4 取消任务 在前面讲到了 Dart 方法执行时是不能被中断的,这就意味着一个 Future 任务开始后必然会走到完成的状态,但是很多时候我们需要又取消一个异步任务,唯一的办法就是在任务结束后不执行回调代码,就可以实现类似取消的效果。 4.5 CancelableOperation 在 Flutter 的 async 包中,提供了一个 CancelableOperation 给我们使用,使用它可以很简单的实现取消任务的需求。 void main() async { // 创建一个可以取消的任务 final cancelableOperation = CancelableOperation.fromFuture( Future(() async { print('start'); await Future.delayed(Duration(seconds: 3)); // 模拟耗时3秒 print('end'); }), onCancel: () => print('cancel...'), ); // 注册任务结束后的回调 cancelableOperation.value.then((val) { print('finished'); }); // 模拟1秒后取消任务 Future.delayed(Duration(seconds: 1)).then((_) => cancelableOperation.cancel()); } CancelableOperation 是对 Future 的代理, 对 Future 的 then 进行了接管,判断 isCanceled 标记决定是否需要执行用户提供的回调。

优秀的个人博客,低调大师

Emojicode —— emoji 编程语言

Emojicode是一种开源的,拥有多范型的结构和流程的语言,可以让你用 Emoji 表情来编写程序。 Emojicode 允许您快速构建跨平台的应用程序同时有很多乐趣。 要求: clang 和 clang++ 6.0.1 或 gcc 和 g++ 7.2 CMake 3.5.1+ 和 Ninja LLVM 7 Python 3.5.2+ 用于测试 步骤: 克隆Emojicode(或下载源代码并解压缩)并导航到其中: git clone https://github.com/emojicode/emojicode cd emojicode 创建一个build目录并在其中运行 CMake: mkdir build cd build cmake .. -GNinja 构建编译器和包: ninja 现在可以测试 Emojicode: ninja tests 二进制文件已准备就绪,可供使用!您可以立即执行 magic installation ninja magicinstall 或者只是正确打包二进制文件和标头 ninja dist 要创建分发存档,必须自己调用 dist 脚本(例如python3 ../dist.py .. archive).

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册