首页 文章 精选 留言 我的

精选列表

搜索[基础搭建],共10000篇文章
优秀的个人博客,低调大师

android登录窗口——基础

大家一定在CS/BS的程序有登录窗口,ANDROID也应该是,下面我来做了一个界面欢迎大家参考! main 代码 packagenet.blogjava.mobile; importandroid.app.Activity; importandroid.app.AlertDialog; importandroid.content.DialogInterface; importandroid.os.Bundle; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.LinearLayout; publicclassMainextendsActivityimplementsOnClickListener { @Override publicvoidonClick(Viewv) { LinearLayoutloginLayout=(LinearLayout)getLayoutInflater().inflate( R.layout.login,null); newAlertDialog.Builder(this).setIcon(R.drawable.login) .setTitle("用户登录").setView(loginLayout).setPositiveButton("登录", newDialogInterface.OnClickListener() { publicvoidonClick(DialogInterfacedialog, intwhichButton) { //编写处理用户登录的代码 } }).setNegativeButton("取消", newDialogInterface.OnClickListener() { publicvoidonClick(DialogInterfacedialog, intwhichButton) { //取消用户登录,退出程序 } }).show(); } @Override publicvoidonCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Buttonbutton=(Button)findViewById(R.id.button); button.setOnClickListener(this); } } 本文转自 llb988 51CTO博客,原文链接:http://blog.51cto.com/llb988/491662,如需转载请自行联系原作者

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

Activity的基础知识

前言 长风破浪会有时,直挂云帆济沧海。 关于Activity的启动和关闭 一个Android应用程序通常都包含多个Activity,但只有一个Activity会作为程序的入口——当该Android应用运行时将会自动启动并执行该Activity。至于应用中的其他Activity,通常都由入口Activity启动,或由入口Activity启动的Activity启动。 Activity启动其他Activity有如下两个方法。 startActivity(Intent intent):启动其他Activity。 startActivityForResult(Intent intent,int requestCode):以指定的请求码(requestCode)启动Activity,而且程序将会获取新启动的Activity返回的结果(通过重写OnActivityResult(...)方法)。 上面两个方法都用到了Intent参数,Intent是Android应用里各组件之间同通信的重要方式,一个Activity通过Intent来表达自己“意图”——想要启动哪个组件,被启动的组件既可是Activity组件,也可是Service组件。 Android为关闭Activity准备了如下两个方法。 finish():结束当前Activity。 finishActivity(int requestCode):结束以startActivityForResult(Intent intent,int requestCode)方法启动的Activity。 代码示例 FirstActivity.java public class FirstActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.first_layout); Button bt = (Button) findViewById(R.id.bt); bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //创建需要启动的Activity对应的Intent Intent intent = new Intent(FirstActivity.this,SecondActivity.class); //启动intent对应的Activity startActivity(intent); } }); } } SecondActivity.java public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.seconde_layout); Button back = (Button) findViewById(R.id.back); Button back_finish = (Button) findViewById(R.id.back_finish); back.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //创建需要启动的Activity对应的Intent Intent intent = new Intent(SecondActivity.this,FirstActivity.class); //启动intent对应的Activity startActivity(intent); } }); back_finish.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //创建需要启动的Activity对应的Intent Intent intent = new Intent(SecondActivity.this,FirstActivity.class); //启动intent对应的Activity startActivity(intent); //结束当前Activity finish(); } }); } } 提示 上述程序的布局文件就只包含简单的按钮来实现跳转,第二个Activity唯一的区别就是finish()方法,它表明该Activity会结束自己。 使用Bundle在Activity之间交换数据 当一个Activity启动另一个Activity时,常常会有一些数据需要传过去。这时Intent就相当于一个“信使”,我们将需要传送的数据存入Intent中即可。、 Intent提供了多个方法来“携带”额外的数据,如下所示。 putExtras(Bundle data):向Intent中放入需要“携带”的数据包。 Bundle getExtras():取出Intent中所“携带”的数据包。 putExtra(String name,Xxx value):向Intent中按key-value对的形式存入数据。 getXxxExtra(String name):从Intent中按key取出指定类型的数据。 上述方法中的Bundle就是一个简单的数据携带包,该Bundle对象包含了多个方法来存入数据。 putXxx(String key, Xxx value):向Bundle中放入Int、Long等各种类型的数据。 putSerializable(String key, Serializable data):向Bundle中放入一个可序列化的对象。 getXxx(String key):从Bundle中取出Int、Long等各种类型的数据。 getSerializable(String key):从Bundle中取出一个可序列化的对象。 下面我通过一个实例来介绍Activity之间如何通过Bundle交换数据。 本程序包含两个Activity,其中第一个Activity用于收集用户的输入信息,当用户单击该Activity的“注册”按钮时,应用进入第二个Activity,第二个Activity将会获取第一个Activity中的数据。 代码示例 FirstActivity.java public class FirstActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.first_layout); Button bn = (Button) findViewById(R.id.bn); bn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { EditText name = (EditText) findViewById(R.id.name); EditText passwd = (EditText) findViewById(R.id.passwd); RadioButton male = (RadioButton) findViewById(R.id.male); String gender = male.isChecked() ? "男" : "女"; Person p = new Person(); p.setName(name.getText().toString()); p.setPasswd(passwd.getText().toString()); p.setGender(gender); //创建一个Bundle对象 Bundle data = new Bundle(); data.putSerializable("person", p); //创建一个Intent Intent intent = new Intent(FirstActivity.this,SecondActivity.class); intent.putExtras(data); //启动intent对应的Activity startActivity(intent); } }); } } first_layout.xml <?xml version="1.0" encoding="utf-8"?> <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请输入您的注册信息" android:textSize="20sp" /> <TableRow> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="用户名:" android:textSize="16sp" /> <EditText android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请填写想注册的账号" android:selectAllOnFocus="true" /> </TableRow> <TableRow> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="密码:" android:textSize="16sp" /> <EditText android:id="@+id/passwd" android:layout_width="match_parent" android:layout_height="wrap_content" android:password="true" android:selectAllOnFocus="true" /> </TableRow> <TableRow> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="性别:" android:textSize="16sp" /> <RadioGroup android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <RadioButton android:id="@+id/male" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="男" android:textSize="16sp" /> <RadioButton android:id="@+id/female" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="女" android:textSize="16sp" /> </RadioGroup> </TableRow> <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="注册" android:textSize="16sp" /> </TableLayout> SecondActivity.java public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.seconde_layout); TextView name = (TextView) findViewById(R.id.name); TextView passwd = (TextView) findViewById(R.id.passwd); TextView gender = (TextView) findViewById(R.id.gender); //获取启动该Activity的Intent Intent intent = getIntent(); //直接通过Intent取出它所携带的Bundle数据包中的数据 Person p = (Person) intent.getSerializableExtra("person"); name.setText("您的用户名为:" + p.getName()); passwd.setText("您的密码为:" + p.getPasswd()); gender.setText("您的性别为:" + p.getGender()); } } seconde_layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center_horizontal" > <TextView android:id="@+id/name" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" /> <TextView android:id="@+id/passwd" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" /> <TextView android:id="@+id/gender" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" /> </LinearLayout> 效果 [图片上传失败...(image-e4b6ea-1514096470518)] [图片上传失败...(image-2ca6b1-1514096470519)] 提示 需要传送数据如果是对象,这个对象应该实现Serializable接口。 启动其他Activity并返回结果 前面已经提到,Activity还提供了一个startActivityForResult(Intent intent,int requestCode)方法来启动其他Activity。该方法用于启动指定Activity,而且期望获取指定Activity返回的结果。这种情况很常见,例如应用程序第一个界面需要用户进行选择,但需要选择的列表数据比较复杂,必须启动另一个Activity让用户选择。当用户在第二个Activity中选择完成后,程序返回第一个Actvity,第一个Activity必须能获取并显示用户在第二个Activity中选择的结果。在这种应用场景下,也通过Bundle进行数据交换的。 为了获取被启动的Activity所返回的结果,需要从两方面着手。 当前Activity需要重写onActivityResult(int requestCode,int resultCode,Intent intent),当被启动的Activity返回结果时,该方法会被触发,其中requestCode代表请求码,而resultCode代表Activtiy返回的结果码,由开发者自行设定。 被启动的Activtiy需要调用setResult()方法设置处理结果。 一个Activity中可能包含多个按钮,并调用多个startActivityForResult()方法来打开多个不同的Activity处理不同的业务,当这些新Activity关闭后,系统将回调前面Activity的onActivityResult(int requestCode,int resultCode,Intent data)方法。为了知道该方法是由哪个请求的结果所触发的,可利用requestCode请求码;为了知道返回的数据来自于哪个新的Activity,可利用resultCode结果码。 代码示例 FirstActivity.java public class FirstActivity extends Activity { Button bt; EditText city; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.first_layout); bt = (Button) findViewById(R.id.bt); city = (EditText) findViewById(R.id.city); bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //创建需要对应于目标Activity的Intent Intent intent = new Intent(FirstActivity.this, SelectCityActivity.class); //启动指定Activity并等待返回的结果,其中0是请求码,用于标识该请求 startActivityForResult(intent, 0); } }); } //重写该方法,该方法以回调的方式来获取指定Activity返回的结果 @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { //当requestCode、resultCode同时为0时,也就是处理特定的结果 if(requestCode == 0 && resultCode == 0) { //取出Intent里德Extras数据 Bundle data = intent.getExtras(); //取出Bundle中的数据 String resultCity = data.getString("city"); //修改city文本框的内容 city.setText(resultCity); } } } SelectCityActivity.java public class SelectCityActivity extends ExpandableListActivity { //定义省份数组 private String[] provinces = new String[] {"广西","广东","湖南","云南"}; private String[][] cities = new String[][] { {"桂林","柳州","南宁","北海"}, {"广州","深圳","珠海","中山"}, {"长沙","岳阳","衡阳","株洲"}, {"昆明","玉溪","大理","丽江"} }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ExpandableListAdapter adapter = new BaseExpandableListAdapter() { @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public boolean hasStableIds() { return true; } private TextView getTextView() { AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64); TextView textView = new TextView(SelectCityActivity.this); textView.setLayoutParams(lp); textView.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT); textView.setPadding(36, 0, 0, 0); textView.setTextSize(20); return textView; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { LinearLayout ll = new LinearLayout(SelectCityActivity.this); ll.setOrientation(LinearLayout.HORIZONTAL); ImageView logo = new ImageView(SelectCityActivity.this); logo.setImageResource(R.drawable.ic_launcher); ll.addView(logo); TextView textView = getTextView(); textView.setText(getGroup(groupPosition).toString()); ll.addView(textView); return ll; } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public int getGroupCount() { return provinces.length; } @Override public Object getGroup(int groupPosition) { return provinces[groupPosition]; } @Override public int getChildrenCount(int groupPosition) { return cities[groupPosition].length; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { TextView textView = getTextView(); textView.setText(getChild(groupPosition, childPosition).toString()); return textView; } @Override public long getChildId(int groupPosition, int childPosition) { // TODO Auto-generated method stub return childPosition; } @Override public Object getChild(int groupPosition, int childPosition) { // TODO Auto-generated method stub return cities[groupPosition][childPosition]; } }; setListAdapter(adapter); //为列表项设置监听 getExpandableListView().setOnChildClickListener(new OnChildClickListener() { @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { //获取启动该Activity之前的Activity对应的Intent Intent intent = getIntent(); intent.putExtra("city", cities[groupPosition][childPosition]); //设置该SelectCityActivity的结果码,并设置结束之后退回的Activity SelectCityActivity.this.setResult(0, intent); //结束SelectCityActivity SelectCityActivity.this.finish(); return false; } }); } } 效果 Screenshot_20171101-145622.png Screenshot_20171101-145711.png Screenshot_20171101-145743.png 提示 别忘记每创建一个新的Activity,都要去清单文件里注册这个Activity。

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

Android 基础操作 git操作

Git 操作 git 命令 创建本地仓库 git init 获取远程仓库 git clone [url] 例:git clone https://github.com/you/yourpro.git 创建远程仓库 // 添加一个新的 remote 远程仓库 git remote add [remote-name] [url] 例:git remote add origin https://github.com/you/yourpro.git origin:相当于该远程仓库的别名 // 列出所有 remote 的别名 git remote // 列出所有 remote 的 url git remote -v // 删除一个 renote git remote rm [name] // 重命名 remote git remote rename [old-name] [new-name] 从本地仓库中删除 git rm file.txt // 从版本库中移除,删除文件 git rm file.txt -cached // 从版本库中移除,不删除原始文件 git rm -r xxx // 从版本库中删除指定文件夹 从本地仓库中添加新的文件 git add . // 添加所有文件 git add file.txt // 添加指定文件 提交,把缓存内容提交到 HEAD 里 git commit -m "注释" 撤销 // 撤销最近的一个提交. git revert HEAD // 取消 commit + add git reset --mixed // 取消 commit git reset --soft // 取消 commit + add + local working git reset --hard 把本地提交 push 到远程服务器 git push [remote-name] [loca-branch]:[remote-branch] 例:git push origin master:master 查看状态 git status 从远程库中下载新的改动 git fetch [remote-name]/[branch] 合并下载的改动到分支 git merge [remote-name]/[branch] 从远程库中下载新的改动 pull = fetch + merge git pull [remote-name] [branch] 例:git pull origin master 分支 // 列出分支 git branch // 创建一个新的分支 git branch (branch-name) // 删除一个分支 git branch -d (branch-nam) // 删除 remote 的分支 git push (remote-name) :(remote-branch) 切换分支 // 切换到一个分支 git checkout [branch-name] // 创建并切换到该分支 git checkout -b [branch-name] ##与github建立ssh通信,让Git操作免去输入密码的繁琐。 首先呢,我们先建立ssh密匙。 ssh key must begin with 'ssh-ed25519', 'ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', or 'ecdsa-sha2-nistp521'. -- from github 根据以上文段我们可以知道github所支持的ssh密匙类型,这里我们创建ssh-rsa密匙。 在command line 中输入以下指令:``ssh-keygen -t rsa``去创建一个ssh-rsa密匙。如果你并不需要为你的密匙创建密码和修改名字,那么就一路回车就OK,如果你需要,请您自行Google翻译,因为只是英文问题。 $ ssh-keygen -t rsa Generating public/private rsa key pair. //您可以根据括号中的路径来判断你的.ssh文件放在了什么地方 Enter file in which to save the key (/c/Users/Liang Guan Quan/.ssh/id_rsa): 到https://github.com/settings/keys这个地址中去添加一个新的SSH key,然后把你的xx.pub文件下的内容文本都复制到Key文本域中,然后就可以提交了。 添加完成之后 我们用ssh git@github.com命令来连通一下github,如果你在response里面看到了你github账号名,那么就说明配置成功了。let's enjoy github ;) gitignore 在本地仓库根目录创建 .gitignore 文件。Win7 下不能直接创建,可以创建 ".gitignore." 文件,后面的标点自动被忽略; /.idea // 过滤指定文件夹 /fd/* // 忽略根目录下的 /fd/ 目录的全部内容; *.iml // 过滤指定的所有文件 !.gitignore // 不忽略该文件

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

Elasticsearch 性能监控基础(转载)

转自:http://blog.csdn.net/yangwenbo214/article/details/74000458 转自:https://www.datadoghq.com/blog/monitor-elasticsearch-performance-metrics/#metrics-to-watch Cloud Insight Elastic Search 监控,默认监控以下性能指标 elasticsearch.active_primary_shards elasticsearch.active_shards elasticsearch.cache.filter.evictions elasticsearch.cache.filter.size elasticsearch.cluster_status elasticsearch.docs.count elasticsearch.docs.deleted elasticsearch.fielddata.evictions elasticsearch.fielddata.size elasticsearch.flush.total elasticsearch.flush.total.time elasticsearch.get.current elasticsearch.get.exists.time elasticsearch.get.exists.total elasticsearch.get.missing.time elasticsearch.get.missing.total elasticsearch.get.time elasticsearch.get.total elasticsearch.http.current_open elasticsearch.http.total_opened elasticsearch.id_cache.size elasticsearch.indexing.delete.current elasticsearch.indexing.delete.time elasticsearch.indexing.delete.total elasticsearch.indexing.index.current elasticsearch.indexing.index.time elasticsearch.indexing.index.total elasticsearch.initializing_shards elasticsearch.merges.current elasticsearch.merges.current.docs elasticsearch.merges.current.size elasticsearch.merges.total elasticsearch.merges.total.docs elasticsearch.merges.total.size elasticsearch.merges.total.size elasticsearch.number_of_nodes elasticsearch.pending_tasks_priority_high elasticsearch.pending_tasks_priority_urgent elasticsearch.pending_tasks_total elasticsearch.process.open_fd elasticsearch.refresh.total elasticsearch.refresh.total.time elasticsearch.relocating_shards elasticsearch.search.fetch.current elasticsearch.search.fetch.open_contexts elasticsearch.search.fetch.time elasticsearch.search.fetch.total elasticsearch.search.query.current elasticsearch.search.query.time elasticsearch.search.query.total elasticsearch.store.size elasticsearch.thread_pool.bulk.active elasticsearch.thread_pool.bulk.queue elasticsearch.thread_pool.bulk.threads elasticsearch.thread_pool.flush.active elasticsearch.thread_pool.flush.queue elasticsearch.thread_pool.flush.threads elasticsearch.thread_pool.generic.active elasticsearch.thread_pool.generic.queue elasticsearch.thread_pool.generic.threads elasticsearch.thread_pool.get.active elasticsearch.thread_pool.get.queue elasticsearch.thread_pool.get.threads elasticsearch.thread_pool.index.active elasticsearch.thread_pool.index.queue elasticsearch.thread_pool.index.threads elasticsearch.thread_pool.management.active elasticsearch.thread_pool.management.queue elasticsearch.thread_pool.management.threads elasticsearch.thread_pool.merge.active elasticsearch.thread_pool.merge.queue elasticsearch.thread_pool.merge.threads elasticsearch.thread_pool.percolate.active elasticsearch.thread_pool.percolate.queue elasticsearch.thread_pool.percolate.threads elasticsearch.thread_pool.refresh.active elasticsearch.thread_pool.refresh.queue elasticsearch.thread_pool.refresh.threads elasticsearch.thread_pool.search.active elasticsearch.thread_pool.search.queue elasticsearch.thread_pool.search.threads elasticsearch.thread_pool.snapshot.active elasticsearch.thread_pool.snapshot.queue elasticsearch.thread_pool.snapshot.threads elasticsearch.transport.rx_count elasticsearch.transport.rx_size elasticsearch.transport.server_open elasticsearch.transport.tx_count elasticsearch.transport.tx_size elasticsearch.unassigned_shards

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

python基础知识(集合)

在python中集合set是一种基本数据的类型,它有可变集合(set())和不可变集合(frozenset)两种。创建集合set、集合set添加、集合删除、交集、并集、差集的操作都是非常实用的方法,接下来将介绍结合的相关知识。 一、集合特点 1、类似字典dict,但是只有key却没有value值; 2、集合的存储没有固定的顺序 3、由于集合里面的元素不能重复所以集合一般用来去重 二、集合的定义 常见的有两种方法 1 2 3 4 5 6 7 1 、直接定义类似字典但是没有value值,例如 set1 = { "openatck" , "and" , "list" , "dict" , "set" } 2 、创建一个 set ,提供一个 list 作为输入集合 set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" ]) 两个的输出结果 { 'openatck' , 'list' , 'and' , 'set' , 'dict' } { 'openatck' , 'list' , 'and' , 'set' , 'dict' } 三、集合元素的操作 1、 增加元素可以使用add()方法增加元素 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" ]) set2.add( "winnerlook" ) print (set1,set2) 结果: { 'set' , 'openatck' , 'and' , 'dict' , 'list' } { 'openatck' , 'winnerlook' , 'list' , 'and' , 'dict' , 'set' } 2、集合元素的增加update()方法 update()是把要传入的元素拆分,做为个体传入到集合中 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set2.update( "winnerlook" , "MYSQlDBA" ) print (set2) 结果: { 'B' , 'M' , 'r' , 'S' , 'Y' , 'e' , 'winnerlook' , 'set' , 'i' , 'Q' ,' and ',' o ',' w ',' n ',' dict ',' k',t} 这时我们发现将我们更新传入的值全部按每个字符当做一个元素插入到当前的集合里面了 3、集合的删除 在前面列表的学习里面我们学习了clear()、pop()、remove()、del等方法可以删除列表中的元素,接下来我们分析一下集合删元素的方法。 clear()方法 clear()方法还是和列表中的一样直接会清空集合中的所有元素,例如: 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" , "winnerlook" ]) #set2.update("winnerlook","MYSQlDBA") set2.clear() print (set1,set2) 结果: { 'set' , 'dict' , 'openatck' , 'list' , 'and' } set () 返回结果和是一个空的集合,而列表使用clear()方法后是返回空的列表 remove()方法 remove()方法是移除集合中的某个元素,但是元素必须存在,不然会报错 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ list = [ "openatck" , "and" , "list" , "dict" , "set" ] set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" , "winnerlook" ]) #set2.update("winnerlook","MYSQlDBA") set2.remove( "winnerlook" ) list .remove( "and" ) print ( list ,set2) 结果: [ 'openatck' , 'list' , 'dict' , 'set' ]{ 'openatck' , 'and' , 'dict' , 'list' , 'set' } pop()方法 集合的pop()方法和列表的pop()方法是不一样的,列表的可以带下标的去删除,列表是默认删除最后一个元素,由于集合的存储是没有固定顺序的所以删除的元素时随机的。我们看一下下面的示例,相同的程序多次执行结果却是不一致。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #!/usr/bin/envpython #_*_coding:utf-8_*_ list = [ "openatck" , "and" , "list" , "dict" , "set" ] set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" , "winnerlook" ]) #set2.update("winnerlook","MYSQlDBA") set2.pop() list .pop() print ( list ,set2) 结果 1 : [ 'openatck' , 'and' , 'list' , 'dict' ]{ 'dict' , 'winnerlook' , 'and' , 'set' , 'list' } #删除openstack 结果 2 : [ 'openatck' , 'and' , 'list' , 'dict' ]{ 'list' , 'set' , 'and' , 'openatck' , 'dict' } #删除winnerlook 结果 3 : [ 'openatck' , 'and' , 'list' , 'dict' ]{ 'list' , 'winnerlook' , 'openatck' , 'set' , 'and' } #删除dict 结果 4 : [ 'openatck' , 'and' , 'list' , 'dict' ]{ 'openatck' , 'dict' , 'winnerlook' , 'and' , 'list' } #删除set 这里为什么是随机删除的,个人猜想是因为集合里面存储顺序不是固定的原因吧,这样就会出现随机 删除的现象。 del 删除 在删除某个定义的集合时,我们还可以采用del方法,这样就可以将一个集合删除,但是这种删除会报没有定义这个集合的错。 1 2 3 4 5 6 7 8 9 10 11 12 #!/usr/bin/envpython #_*_coding:utf-8_*_ list = [ "openatck" , "and" , "list" , "dict" , "set" ] set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openatck" , "and" , "list" , "dict" , "set" , "winnerlook" ]) #set2.update("winnerlook","MYSQlDBA") del set2 list .pop() print ( list ,set2) 结果: print ( list ,set2) NameError:name 'set2' is not defined discard()方法 discard() 接受一个单值作为参数,并从集合中删除该值。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 list2 [ 'winner' , 'mysql5.6' , 'mariadb' , 'redis' , 'tomcat' , 'redis' , 'DBA' , 'linuxSRA' ] >>>s3 = set (list2) >>>s3 { 'winner' , 'DBA' , 'linuxSRA' , 'mysql5.6' , 'mariadb' , 'tomcat' , 'redis' } >>>s3.discard( "DBA" ) >>>s3 { 'winner' , 'linuxSRA' , 'mysql5.6' , 'mariadb' , 'tomcat' , 'redis' } >>>s3.discard( "DBA" ) #删除没有的元素没有结果 再看看remove() >s3.remove( "winner" ) >>>s3.remove( "winner" ) Traceback(mostrecentcalllast): File "<pyshell#50>" ,line 1 , in <module> s3.remove( "winner" ) KeyError: 'winner' 小结: 1.discard() 接受一个单值作为参数,并从集合中删除该值。 2.如果针对一个集合中不存在的值调用 discard() 方法,它不进行任何操作。不产生错误;只是一条空指令。 3. remove() 方法也接受一个单值作为参数,也从集合中将其删除。 4. 区别在这里:如果该值不在集合中,remove() 方法引发一个 KeyError 例外。 4、集合的访问 由于集合本身是无序的,所以不能为集合创建索引或切片操作,只能循环遍历或使用in、not in来访问或判断集合元素。 5、元素与集合、集合与集合的关系 在我们高中学习集合相关的知识时,我们就学习到集合的交际、并集、补集等概念,而这部分概念在其python编程的数据类型集合里面还是适用的。 下面简单的演示以下上面的集合关系和相关的操作: 元素与集合的关系: in 一般是用来表示某个元素是否在某个集合里面,返回值为Ture和False 1 2 3 4 5 6 7 8 9 10 11 #!/usr/bin/envpython #_*_coding:utf-8_*_ list = [ "openatck" , "and" , "list" , "dict" , "set" ] set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) print ( "openstack" in set2) print ( "docker" in set2) 结果: True False 由于set2中包含openstack元素但是不包含docker元素,所以判断一个返回Ture,一个返回 False not in 其实和in表达的意思差不多 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/envpython #_*_coding:utf-8_*_ list = [ "openatck" , "and" , "list" , "dict" , "set" ] set1 = { "openatck" , "and" , "list" , "dict" , "set" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) print ( "openstack" not in set2) print ( "docker" not in set2) 结果: False True == 等于关系 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/envpython #_*_coding:utf-8_*_ set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set3 = { "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" } print (set2 = = set3) 结果: True 表示两个集合相等 set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set3 = { "openstack" , 17 , "list" , "dict" , "set" , "winnerlook" } print (set1 = = set3) 结果: True 表示两个集合相等表达式和结果一样 != 不等于关系 表示两个集合的元素不一样 1 2 3 4 5 6 7 8 9 10 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set3 = { "openstack" , 17 , "list" , "dict" , "set" , "winnerlook" } print (set1! = set2) print (set1! = set3) 结果: True False 集合与集合的关系 子集(<)与真子集(<=) 子集表示一个集合里面的元素被另一个集合包含,而真子集是说的一个集合的元素恰好和另一个集合相等。 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set3 = { "openstack" , 17 , "list" , "dict" , "set" , "winnerlook" } set4 = { "openstack" , "list" , "dict" , "set" , "winnerlook" } print (set1< = set3) print (set4<set1) print (set4< = set3) 结果: True True True 严格超集(>)和非严格超集(>=) 这里的关系和上面的字迹关系是一样的,只不过是用的表示相反的关系 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "and" , "list" , "dict" , "set" , "winnerlook" ]) set3 = { "openstack" , 17 , "list" , "dict" , "set" , "winnerlook" } set4 = { "openstack" , "list" , "dict" , "set" , "winnerlook" } print (set1> = set3) print (set4>set1) print (set4> = set3) 结果: True False False 交集(&)或者用intersection() 表示两个集合中相同的元素 1 2 3 4 5 6 7 8 9 10 11 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} print (set1&set2) print (set1.intersection(set2)) 结果: { 'openstack' , 'list' , 'dict' , 'winnerlook' } { 'openstack' , 'list' , 'dict' , 'winnerlook' } 并集 (|)或者用union()表示 表示两个集合中一共包含的元素 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} #print(set1&set2) #print(set1.intersection(set2)) print (set1|set2) print (set1.union(set2)) 结果: { 0.99 , 99 , 100 , 'dict' , 'set' , 17 , 'winnerlook' , 'list' , 'openstack' } { 0.99 , 99 , 100 , 'dict' , 'set' , 17 , 'winnerlook' , 'list' , 'openstack' } 差补(-)或者difference() 相对补集 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} #print(set1&set2) #print(set1.intersection(set2)) print (set1 - set2) print (set1.difference(set2)) 结果: { 17 , 'set' } { 17 , 'set' } set2相对sst1的补集即set2中有,但是set1中是没有的 对称差分(^)或者symmetric_difference() 对称差分是集合的XOR(‘异或’),取得的元素属于set1,set2但不同时属于set1和set2 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} #print(set1&set2) #print(set1.intersection(set2)) print (set1^set2) print (set1.symmetric_difference(set2)) 结果: { 0.99 , 17 , 99 , 100 , 'set' } { 0.99 , 17 , 99 , 100 , 'set' } 6、集合之间的and与or关系 注意and关系是取值set2 or关系是取值set1 1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} #print(set1&set2) #print(set1.intersection(set2)) print (set1 and set2) print (set1 or set2) { 0.99 , 99 , 100 , 'dict' , 'winnerlook' , 'list' , 'openstack' } { 'dict' , 'set' , 'winnerlook' , 17 , 'list' , 'openstack' } 7、集合、列表、元组、字符串之间转换 我们可以将集合根据不同的数据类型转换成其他的格式 list(set1)将集合转换成列表 tuple(set1)将集合转换成元组 str(set1) 将集合转换成字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #!/usr/bin/envpython #_*_coding:utf-8_*_ set1 = { "openstack" , 9 + 8 , "list" , "dict" , "set" , "winnerlook" } set2 = set ([ "openstack" , "list" , "dict" , "winnerlook" , 99 , 100 , 0.99 ]) #set3={"openstack",17,"list","dict","set","winnerlook"} #set4={"openstack","list","dict","set","winnerlook"} #print(set1&set2) #print(set1.intersection(set2)) print ( str (set1), type ( str (set1))) print ( list (set1), type ( list (set1))) print ( tuple (set1), type ( tuple (set1))) 结果: { 'set' , 'list' , 'winnerlook' , 'dict' , 17 , 'openstack' }< class 'str' > [ 'set' , 'list' , 'winnerlook' , 'dict' , 17 , 'openstack' ]< class 'list' > ( 'set' , 'list' , 'winnerlook' , 'dict' , 17 , 'openstack' )< class 'tuple' > 8、集合的简单应用 由于集合的元素不能重复,所以可以用来去重 1 2 3 4 5 list2 = [ 2 , - 3 , - 8 , 0 , 100 , 5005 , 737737 , 10010 , - 3 , - 8 , 0 , 100 , 10010 ] set222 = set (list2) print (set222) 结果: { 0 , 2 , 100 , 737737 , 5005 , - 8 , 10010 , - 3 } 四、集合的内建函数与内建方法 1、len():返回集合元素个数 2、set()、frozenset()工厂函数 3、所有集合方法: 4、仅适合可变集合的 本文转自 tianya1993 51CTO博客,原文链接:http://blog.51cto.com/dreamlinux/1910566,如需转载请自行联系原作者

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

SQL Server内存架构基础

翻译自: https://mssqlwiki.com/sqlwiki/sql-performance/basics-of-sql-server-memory-architecture/ 1.32位SQL Server内存架构 在Win32内存架构里,每个进程有4GB的虚拟地址空间。默认情况下,2GB的地址空间可从用户模式访问(应用程序像SQL Server),剩下的2GB可从内核模式访问。 所以,在32位Windows架构里,SQL Server最大可用内存为2GB。 注意:当/3GB开关启用后,用户模式地址空间变为3GB,而内核模式变为1GB。当32位SQL Server运行在64位Windows下(WOW64),它获得4GB的用户地址空间。它也可以在WOW64模式下影响AWE,并可以使用多于4GB内存。 SQL Server“用户地址空间(User address space)”分为两个部分:MemToleave和Buffer Pool。 MemToLeave(MTL)和Buffer Pool(BPool)的大小由SQLServer在启动时决定,如下: MTL(Memory to Leave) = (Stack size * max worker threads) +Additional space(By default 256 MB and can be controlled by -g) Stack size = 512 KB per thread for 32 Bit SQL Server I.e = (256 * 512KB) + 256MB = 384MB 加载DLL的额外空间从SQL Server 2000开始为256MB。该空间用于存储: COM对象 扩展存储过程 进程中加载的链接服务器的内存分配或者在SQL Server进程中其他DLL的加载 SQL Server内存管理器的内存分配,如果分配大小大于8K需要持续内存(Multiple_pages_kb)。 SQLCLR 注意,加载DLL的额外空间可以使用-g启动参数修改。 在任何机器上,使用少于4个处理器时,最大工作线程(Maximum worker Thread)默认总是为256MB(除非,我们使用sp_configure修改该值)。 SQL Server Buffer Pool为“Phyiscal RAM”和“user modememory(2GB or 3GB) - MTL”的最小值- BUF structures: BPool = Minimum(Physical memory, User address space – MTL) –BUF structures 为了确保MemToLeave持续分配,SQL Server首先保留MTL,然后是所有的Buffer Pool区域,最后释放MemToLeave区域。 在BPOOL中是什么? 数据页/索引页和SQL Server内存管理器分配的内存,用于以下memory clerk之一。如果内存请求<=8KB。 CACHESTORE_PHDR CACHESTORE_XMLDBTYPE CACHESTORE_EVENTS MEMORYCLERK_SQLSTORENG MEMORYCLERK_XE CACHESTORE_XPROC OBJECTSTORE_SNI_PACKET CACHESTORE_BROKERRSB OBJECTSTORE_SERVICE_BROKER MEMORYCLERK_SQLSERVICEBROKERTRANSPORT MEMORYCLERK_XE_BUFFER CACHESTORE_XMLDBATTRIBUTE MEMORYCLERK_SQLOPTIMIZER USERSTORE_OBJPERM USERSTORE_TOKENPERM CACHESTORE_FULLTEXTSTOPLIST MEMORYCLERK_SQLGENERAL MEMORYCLERK_SQLHTTP CACHESTORE_NOTIF CACHESTORE_XMLDBELEMENT OBJECTSTORE_LOCK_MANAGER MEMORYCLERK_SQLBUFFERPOOL MEMORYCLERK_SQLSOAP MEMORYCLERK_TRACE_EVTNOTIF CACHESTORE_CONVPRI MEMORYCLERK_QSRANGEPREFETCH CACHESTORE_BROKERREADONLY MEMORYCLERK_SQLCLRASSEMBLY MEMORYCLERK_SOSNODE CACHESTORE_STACKFRAMES MEMORYCLERK_SQLCONNECTIONPOOL MEMORYCLERK_SQLSERVICEBROKER CACHESTORE_OBJCP MEMORYCLERK_SQLQUERYPLAN OBJECTSTORE_SECAUDIT_EVENT_BUFFER OBJECTSTORE_LBSS MEMORYCLERK_FULLTEXT CACHESTORE_TEMPTABLES CACHESTORE_BROKERTBLACS MEMORYCLERK_SQLXML USERSTORE_SXC MEMORYCLERK_BHF CACHESTORE_SQLCP CACHESTORE_SYSTEMROWSET USERSTORE_SCHEMAMGR MEMORYCLERK_SQLQUERYCOMPILE CACHESTORE_BROKERTO CACHESTORE_BROKERKEK MEMORYCLERK_SNI MEMORYCLERK_FULLTEXT_SHMEM CACHESTORE_BROKERUSERCERTLOOKUP USERSTORE_DBMETADATA CACHESTORE_VIEWDEFINITIONS MEMORYCLERK_SQLQUERYEXEC CACHESTORE_BROKERDSH MEMORYCLERK_SQLSOAPSESSIONSTORE MEMORYCLERK_SQLQERESERVATIONS MEMORYCLERK_HOST MEMORYCLERK_SQLXP MEMORYCLERK_SQLUTILITIES 在MTL(Non-BPool)中是什么? COM对象 SQL Server CLR 链接服务器OLEDB提供者分配的内存和在SQL Server进程里第三方DLL的加载 扩展存储过程 网络包 内存管理器消耗的内存。如果内存请求>8KB,并需要持续分配。 BUF Structures是什么? SQL Server对每一页维护着一个BUF结构。该结构用于跟踪与每个buffer相关的状态信息,像buffer latch,一个指向实际8KB页的指针,状态位表明该页是否为脏页,有IO处理。 注意,当AWE启用后,BUF structure维护对于整个RAM调整最大服务器内存不用重启SQL Server。 PAE是什么? PAE用于增加32位处理器寻址多于4GB物理内存的能力。在boot.ini中,启用/PAE使得操作系统利用多于4GB物理内存。 什么是SQL Server里的AWE? 当AWE启用,32位的SQL Server将能够使用AWE分配器API寻址多于4GB物理内存。 注意,在32位SQL Server里,只有数据页和索引页可以放在AWE内存里。因此,对于其他SQL Server内存对象的可用内存仍然被限制在用户地址空间。 使用AWE分配器API的内存分配不是进程工作集的一部分,因此不能被页交换,在任务管理和perfmon里private bytes或者working set部分不可见。 SQL Server启动账号需要内存中锁定页面权限来使用AWE分配器API。 在64位系统里,如果你有AWE分配器API用于分配内存的SQL Server启动账号的内存锁定页面权限,那sp_configure ‘awe enabled’没有任何作用。 /3GB开关是什么? /3GB开关用于Boot.ini文件。 当我们启用/3GB。SQL Server的用户地址空间或者任何使用IMAGE_FILE_LARGE_ADDRESS_AWARE的应用程序将会增加到3GB,而限制内核模式地址空间为1GB。 当系统中的物理内存超过16GB,并且使用/3GB开关,操作系统将会忽略额外的内存,直到/3GB开关被移除。这是因为内核增加的大小需要支持更多页面表条目(Page table Entries)。 AWE如何工作?AWE分配器API是什么? AWE API激活程序寻址多于通过标准32位寻址的4GB内存。 AWE API如何使用? 匹配AWE页面分配地址空间。 ADD=VirtualAlloc(lpaddress,size,MEM_RESERVE |MEM_PHYSICAL,PAGE_READWRITE); 分配不能被页交换的物理内存。 bResult=AllocateUserPhysicalPages(GetCurrentProcess(),&sizemap,aRAMPages); 匹配一个到你地址空间的页面视图。 bResult=MapUserPhysicalPages(ADD,sizemap,aRAMPages); 2.64位SQL Server内存架构 在64位Windows里,每个进程获得高达8TB的地址空间,因此SQL Server不需要预留一定的内存地址空间用于Non-Bpool分配。 在64位SQL Server里有三种内存模型: Conventional–普通物理页面大小(4/8KB),内存可以页交换,动态的 Locked–普通物理页面大小(4/8KB),Bpool不能被页交换,动态的,需要SQLServer启动账号有内存中锁定页面权限,内存通过使用AWE API分配 Large–大物理页面大小(>=2MB),不可页交换,静态,在启动时内存确定,推荐使用“Max server memory”,需要SQL Server启动账号有内存中锁定页面权限和TF834(只在企业版支持,使用>8GB内存)。 内存计算在64位SQL Server是非常明确的。 SQL Server在启动时计算内存大小并保留它,minimum(reserved space, “Max server memory”)用于Bpool。 类似于32位SQL Server,在64位SQL Server也有Bpool外的内存分配,被称为Non-Bpool分配。 在Bpool外谁分配内存? COM对象 SQL Server CLR 链接服务器OLEDB提供者和在SQL Server进程里第三方DLL加载的内存分配 扩展存储过程 网络包 通过内存管理器消耗的内存。如果内存请求大于8KB并且需要持续分配。 备份 线程的内存(在64位SQL Server里stack size是2MB) 最大服务器内存只控制了Bpool,它不控制Non-Bpool分配,这就是为什么SQLServer内存使用大于“Max server memory”的原因。 总结: 当“内存中锁定页面被使用”操作系统不能页交换出Bpool,而Non-Bpool分配仍可以被页交换。 Sp_configure “awe enabled”选项在64位SQL Server里没有用。 “Max server memory”只限制Bpool,因此SQL Server内存使用将会大于“Max server memory”。 如果你的操作系统是Windows 2003(Windows 2008的话随便你),确保先考虑被其他应用程序、操作系统、驱动、SQL Server Non-Bpool分配等需要的内存,然后设置合适的SQL Server最大服务器内存。 注意:以上架构适用于SQL Server2008 R2及以下版本。SQL Server 2012(Denali)与之前版本相比,内存管理器在有效地方式管理SQL Server内存消耗上做出了很多改变。点击这里,了解SQL Server 2012内存架构。 内存体系结构(SQL Server2008 R2) https://msdn.microsoft.com/zh-cn/library/ms187499.aspx 本文转自UltraSQL51CTO博客,原文链接:http://blog.51cto.com/ultrasql/1789618 ,如需转载请自行联系原作者

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

mysql基础(八)mysql日志

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 mysql日志类型: 1 、查询日志(通常不会开启,也不建议开启) 2 、慢查询日志(建议开启) 3 、错误日志(建议开启) 4 、二进制日志(建议开启) 5 、中继日志 6 、事务日志(帮助事务型存储引擎完成ACID测试) mysql>SHOWGLOBALVARIABLESLIKE '%log%' ; #查看和日志相关的变量 查询日志: general_log = ON|OFF #是否开启查询日志 general_log_file = PATH #查询日志文件路径 log_output = FILE |TABLE|NONE #输出方式,默认为FILE 慢查询日志:执行时长超出指定时长的查询操作 mysql>SHOWGLOBALVARIABLESLIKE 'long_query_time' ; #查看超时时长 服务器变量: slow_query_log = ON|OFF #是否开启慢查询日志 log - slow - queries = PATH #慢查询日志存储路径,默为HOSTNAME-slow.log log_output = FILE |TABLE #输出方式,默认为FILE mysqldumpslow #慢查询日志分析工具 错误日志: 1 、记录mysql启动和关闭过程中产生的事件信息 2 、记录mysql运行过程中产生的错误信息 3 、在主从架构中,从服务器上启动从服务器线程产生的信息 服务器变量: log_error = OFF|ON|PATH #启动错误日志,如果不指定错误日志位置将使用默认位置 log_warnings = 0 | 1 #是否记录警告信息 二进制日志:记录导致数据改变或者有可能导致数据发生改变的SQL语句 功能:用于实现通过 "重放" 日志文件中的事件来生成数据副本 mysql>SHOWMASTERLOGS; #查看可使用的二进制日志文件列表 mysql>SHOWMASTERSTATUS; #查看正在使用的二进制日志文件 mysql>SHOWBINLOGEVENTS; #查看二进制日志文件内容 服务器变量: sql_log_bin = OFF|ON #是否开启二进制日志 log_bin = OFF|ON #是否开启二进制日志,必须同时启用才能生效 binlog_format = STATEMENT|ROW|MIXED #二进制日志格式 max_binlog_size = #单个二进制文件最大大小 1 、到达最大大小时自动滚动 2 、重启后自动滚动 sync_binlog = 0 | 1 #是否同步写入,默认为异步写入 1 、同步写入会影响服务器性能 2 、异步写入可能会造成数据丢失 二进制文件格式: 基于语句的记录:STATEMENT 优点:在相同体积下记录的数据更多 缺点:不能保证回放的数据和源数据完全相同 如:mysql>INSERTINTOtestVALUE( 1 ,now()); #每一次获取的系统时间都不相同 基于行(数据)的记录:ROW 优点:能保证回放的数据和源数据基本相同 缺点:在相同体积下记录的数据更少 混合模式:MIXED,由系统判定基于那种方式进行存储 二进制文件的构成: 日志文件:mysql - bin . 00000X #二进制文件 索引文件:mysql - bin .index #保存当前可用的二进制日志文件列表 二进制日志事件的格式: mysqlbinlog #二进制文件分析工具 使用格式:mysqlbinlog[ - - start - position = 事件开始位置]二进制日志文件 例:mysqlbinlogmysql - bin . 000003 #at655 #1702208:33:37serverid1end_log_pos731Querythread_id=12exec_time=0error_code=0 SET TIMESTAMP = 1487550817 / * ! * / ; BEGIN / * ! * / ; 事件的起始位置:at 655 事件发生的时间: 170220 8 : 33 : 37 server id 1 :server id ,在做mysql集群时必须保证server id 全局唯一 事件的结束位置:end_log_pos 731 事件的类型:Query 事件发生时所在服务器执行此事件的线程 ID :thread_id = 12 语句执行和将其写入二进制日志中的时间差 错误代码:error_code 中继日志:主从架构中实现主从复制的从服务日志,主要用于保存从二进制日志文件中读取事件 事务日志: 由事务型存储自行管理和使用 清理日志: PURGEBINARYLOGSTO 'mysql-bin.010' ; #清除指定日志之前的二进制日志 PURGEBINARYLOGSBEFORE '2008-04-0222:46:26' ; #清除指定时间之前的二进制日志 本文转自 红尘世间 51CTO博客,原文链接:http://blog.51cto.com/hongchen99/1933882

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

Android--Service之基础

Service概述 与开发一个Activity类似,它需要继承Service这个抽象类,并在实现类中,需要重写一些回调方法,用于处理Service的生命周期各部分的操作。而Service也是继承自Context,因此它也可以调用Context里定义的如getResource()、getContentResolver()等方法。 Service中定义的生命周期方法,对Service服务的开发大部分工作就围绕以下几个方法进行操作: void onCreate():当该Service第一次被创建后将立即回调该方法。 void onStartCommand(Intent intent,int flags,int startId):每次通过startService()方法启动Service时都会被回调。 void onDestroy():当Service被关闭前会被回调。 abstract IBinder onBind(Intent intent):该方法是Service子类必须实现的方法,如果不需要通过绑定的方式启动服务,可以返回Null。 boolean onUnbind(Intent intent):当Service上绑定的所有客户端都断开连接将回调该方法。 通过服务的启动方式与适用范围,可将服务分为两类服务: start:启动服务,当一个Android组件(如一个Activity)调用startService()的时候,启动一个服务。服务一旦启动,就可以一直在后台运行下去,即使这个启动它的组件被摧毁。这样的服务模式,通常用于执行一个操作而不需要返回结果给调用者。 Bound:绑定服务,当一个Android组件(如一个Activity)调用bindService()。一个绑定服务提供了一个客户端到服务端的接口,允许组件与服务之间进行交互,这样可以实现跨进程的通信。绑定服务的生命周期默认是跟随它的绑定组件的,但是一个绑定服务可以绑定多个Android组件,如果这些Android组件都被销毁,那么这个绑定服务也将被销毁。 虽然上面提到了服务有两种类别,但是一个服务类所要继承的类是一样的,都是Service类。也就是说,一个服务,可以包含上面两种运行方式的服务,只是与它重载的方法有关,如果重写了onStartCommand()即支持启动服务,如果重写onBiind()即支持绑定服务,所以如果同时重载实现这两个方法即可实现两种服务。 而对于两种启动方式的服务,生命周期中被回调的方法也不一样,下图明确说明了Service两种情况下的生命周期: 清单文件的配置 Service是Android四大组件之一,所以它也必须在AndroidManifest清单文件中进行配置,否则系统将找不到这个服务。与Activity一样,Service的配置也是在<application/>节点下,使用<service/>配置,其中android:name属性为Service类。 如果开发的服务需要被外部应用操作,还需要配置<intent-filter/>节点,但是如果仅本程序使用,则无需配置它也可以。 如果这个服务强制仅本应用操作,可以配置<service/>节点的android:exported属性为false,这样即使配置了<intent-filter/>,外部应用也无法操作这个服务,android:exported属性默认为true。 清单文件配置示例: 1 <application> 2 <!-- 普通的服务 --> 3 <service android:name=".Service1"></service> 4 <!-- 可被外部应用访问的服务 --> 5 <service android:name=".Service2"> 6 <intent-filter > 7 <action android:name="com.bgxt.Service2"/> 8 </intent-filter> 9 </service> 10 <!-- 无法被外部应用访问的服务 --> 11 <service android:name=".Service3" android:exported="false"> 12 <intent-filter > 13 <action android:name="com.bgxt.Service3"/> 14 </intent-filter> 15 </service> 16 </application> Service的开发步骤 既然Service是一个与Activity类似的Android组件,所以它的开发步骤大致也为一下几步: 开发一个服务类,需要继承Service或者IntentService。 在AndroidManifest清单文件中注册Service组件。 在一个Android组件中启动这个开发的Service组件。 服务使用完成之后,需要停止这个服务。 启动服务 启动服务必须实现Service.onStartCommond()方法。启动服务使用startService(Intent intent)方法开启一个服务,仅需要传递一个Intent对象即可,在Intent对象中指定需要启动的服务。而使用startService()方法启动的服务,在服务的外部,必须使用stopService()方法停止,在服务的内部可以调用stopSelf()方法停止当前服务。一旦使用startService()或者stopSelf()方法请求停止服务,系统会就会尽快销毁这个服务。 对于启动服务,一旦启动将与访问它的组件无任何关联,即使访问它的组件被销毁了,这个服务也一直运行下去,直到被销毁! 启动服务-示例 下面开发一个简单的使用startService()启动的服务,首先开发一个服务类: 1 package com.example.intentdemo2; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.IBinder; 6 import android.util.Log; 7 8 public class StartService extends Service { 9 private final static String TAG = "main"; 10 11 @Override 12 public IBinder onBind(Intent arg0) { 13 // 仅通过startService()启动服务,所以这个方法返回null即可。 14 return null; 15 } 16 17 @Override 18 public void onCreate() { 19 super.onCreate(); 20 Log.i(TAG, "Service is Created"); 21 } 22 23 @Override 24 public int onStartCommand(Intent intent, int flags, int startId) { 25 Log.i(TAG, "Service is started"); 26 return super.onStartCommand(intent, flags, startId); 27 } 28 29 @Override 30 public void onDestroy() { 31 Log.i(TAG, "Service is Destroyed"); 32 super.onDestroy(); 33 } 34 35 } 虽然这个Service类没有什么处理逻辑,但是它包含了Service框架,在实际开发过程中,只需要在其中回调的方法中加入实际的业务实现代码即可。下面再使用一个Activity来操作这个服务,在这个Activity中有两个按钮,分别用于启动和停止这个服务。 1 package com.example.intentdemo2; 2 3 import android.app.Activity; 4 import android.content.ComponentName; 5 import android.content.Intent; 6 import android.os.Bundle; 7 import android.util.Log; 8 import android.view.View; 9 import android.widget.Button; 10 11 public class ServiceActivity1 extends Activity { 12 private Button btnSer1, btnSer2; 13 private Intent service=null; 14 @Override 15 protected void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 setContentView(R.layout.activity_service1); 18 btnSer1 = (Button) findViewById(R.id.btnSer1); 19 btnSer2 = (Button) findViewById(R.id.btnSer2); 20 // 设置服务启动的Intent 21 service=new Intent(ServiceActivity1.this,StartService.class); 22 btnSer1.setOnClickListener(new View.OnClickListener() { 23 24 @Override 25 public void onClick(View v) { 26 // 启动服务 27 startService(service); 28 } 29 }); 30 31 btnSer2.setOnClickListener(new View.OnClickListener() { 32 33 @Override 34 public void onClick(View v) { 35 // 停止服务 36 stopService(service); 37 } 38 }); 39 } 40 } 执行结果均在日志中,可以在LogCat中查看,先启动服务,再停止服务: 绑定服务 如果Service和宿主之间需要进行方法调用或者数据交换,则应该使用Context对象的bindService()和unbindService()方法来绑定和解除绑定服务。 Context的bindService()方法的完整方法签名为: bindService(Intent service,ServiceConnection conn,int flags) 下面简单介绍一下这个方法的三个参数的意义: service:通过Intent指定要绑定的Service。 conn:一个ServiceConnection对象,该对象用于监听访问者与Service对象的onServiceConnected()方法。 flags:指定绑定时是否自动创建Service。0不自动创建、BIND_AUTO_CREATE,自动创建。 从上面的bindService方法可以看出,绑定一个服务于宿主交互,依托于一个ServiceConnection接口,这个接口对象必须声明在主线程中,通过实现其中的两个方法,来实现与Service的交互,下面分别介绍一下这两个方法: void onServiceConnection(ComponentName name,IBinder service):绑定服务的时候被回调,在这个方法获取绑定Service传递过来的IBinder对象,通过这个IBinder对象,实现宿主和Service的交互。 void onServiceDisconnected(ComponentName name):当取消绑定的时候被回调。但正常情况下是不被调用的,它的调用时机是当Service服务被意外销毁时,例如内存的资源不足时这个方法才被自动调用。 在使用绑定的服务的时候,该Service类必须提供一个IBinder onBind(Intent intent)方法,在绑定本地Service的情况下,onBind()方法说返回的IBinder对象会传给宿主的ServiceConnection.onServiceConnected()方法的service参数,这样宿主就可以通过IBinder对象与Service进行通信。实际开发中一般会继承Binder类(IBinder的实现类)的方式实现自己的IBinder对象。 需要注意的是,如果绑定服务提供的onBind()方法返回为Null,则也可以使用bindService()启动服务,但不会绑定上Service,因此宿主的ServiceConnection.onServiceConnected()方法不会被执行,也就不存在于宿主与服务的交互。 绑定服务-示例 说了这么多绑定服务相关的内容,下面通过一个例子来实现Service的绑定与数据交互。 开发一个Service类,用于进行绑定,在Service类中,做一个简单的数值累加,每秒加一。 1 package com.example.intentdemo2; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.Binder; 6 import android.os.IBinder; 7 import android.util.Log; 8 9 public class BindService extends Service { 10 private final static String TAG = "main"; 11 private int count; 12 private boolean quit; 13 14 private Thread thread; 15 private MyBinder binder=new MyBinder(); 16 public class MyBinder extends Binder 17 { 18 // 声明一个方法,把count暴露给外部程序。 19 public int getCount(){ 20 return count; 21 } 22 } 23 24 @Override 25 public void onCreate() { 26 super.onCreate(); 27 Log.i(TAG, "Service is Created"); 28 thread=new Thread(new Runnable() { 29 @Override 30 public void run() { 31 // 每间隔一秒count加1 ,直到quit为true。 32 while(!quit){ 33 try{ 34 Thread.sleep(1000); 35 }catch(InterruptedException e){ 36 e.printStackTrace(); 37 } 38 count++; 39 } 40 } 41 }); 42 thread.start(); 43 } 44 45 @Override 46 public boolean onUnbind(Intent intent) { 47 Log.i(TAG, "Service is Unbinded"); 48 return true; 49 } 50 51 @Override 52 public int onStartCommand(Intent intent, int flags, int startId) { 53 Log.i(TAG, "Service is started"); 54 return super.onStartCommand(intent, flags, startId); 55 } 56 57 @Override 58 public void onDestroy() { 59 super.onDestroy(); 60 Log.i(TAG, "Service is Destroyed"); 61 this.quit=true; 62 63 } 64 65 @Override 66 public IBinder onBind(Intent intent) { 67 Log.i(TAG, "Service is Binded"); 68 return binder; 69 } 70 } 然后使用一个Activity来绑定上面这个Service类,并且声明一个ServiceConnection对象,用于进行数据交互。 1 package com.example.intentdemo2; 2 3 import android.app.Activity; 4 import android.app.Service; 5 import android.content.ComponentName; 6 import android.content.Intent; 7 8 import android.content.ServiceConnection; 9 import android.os.Bundle; 10 import android.os.IBinder; 11 import android.util.Log; 12 import android.view.View; 13 import android.widget.Button; 14 import android.widget.Toast; 15 16 public class ServiceActivity2 extends Activity { 17 private final String TAG = "main"; 18 Button bind, unbind, getServiceStatus; 19 BindService.MyBinder binder; 20 private ServiceConnection conn = new ServiceConnection() { 21 @Override 22 public void onServiceDisconnected(ComponentName name) { 23 Log.i(TAG, "--Service Disconnected--"); 24 } 25 @Override 26 public void onServiceConnected(ComponentName name, IBinder service) { 27 Log.i(TAG, "--Service Connected--"); 28 // 取得Service对象中的Binder对象 29 binder = (BindService.MyBinder) service; 30 } 31 }; 32 33 @Override 34 protected void onCreate(Bundle savedInstanceState) { 35 super.onCreate(savedInstanceState); 36 setContentView(R.layout.activity_bindservice1); 37 38 bind = (Button) findViewById(R.id.bind); 39 unbind = (Button) findViewById(R.id.unbind); 40 getServiceStatus = (Button) findViewById(R.id.getServiceStatus); 41 42 final Intent intent = new Intent(); 43 // 指定开启服务的action 44 intent.setAction("com.bgxt.BindServiceDemo"); 45 46 bind.setOnClickListener(new View.OnClickListener() { 47 48 @Override 49 public void onClick(View v) { 50 // 绑定服务到当前activity中 51 bindService(intent, conn, Service.BIND_AUTO_CREATE); 52 } 53 }); 54 unbind.setOnClickListener(new View.OnClickListener() { 55 56 @Override 57 public void onClick(View v) { 58 // 解除绑定 59 binder=null; 60 unbindService(conn); 61 } 62 }); 63 getServiceStatus.setOnClickListener(new View.OnClickListener() { 64 65 @Override 66 public void onClick(View v) { 67 if(binder!=null) 68 { 69 // 通过绑定服务传递的Binder对象,获取Service暴露出来的数据 70 Toast.makeText(ServiceActivity2.this, 71 "Service的Count值为" + binder.getCount(), 72 Toast.LENGTH_SHORT).show(); 73 Log.i(TAG, "Service的Count值为" + binder.getCount()); 74 } 75 else 76 { 77 Toast.makeText(ServiceActivity2.this, 78 "还没绑定呢,先绑定。", 79 Toast.LENGTH_SHORT).show(); 80 } 81 } 82 }); 83 } 84 } 执行结果,先绑定服务,然后获取当前服务运行时count的值,最后解除绑定,把执行过程输出到LogCat中。 Service的选用 相信看完以上的内容,对Android下Service组件有了一定的了解,但是对于选用startService()还是使用bindService(),有一些原则需要讲明。如果仅仅是想要启动一个后台服务长期驻留在内存中执行某项任务,那么仅使用startService()启动一个服务即可。但是如果想要与正在运行的服务进行交互,一种方式是使用broadcast,这个以后再介绍,另外一种方式就是使用bindService()绑定一个服务到组件上,使用broadcast的缺点是如果数据交互频繁,容易造成性能上的问题,并且BroadcastReceiver本身执行代码的时间不确定,也许代码执行到一半,后面的代码将不被执行,但是使用bindService()绑定服务即没有这些问题。另外,如果一个服务是依托于某项应用的,那么也最好使用绑定服务,在依托的应用启动的时候绑定服务,这样可以在不使用的时候避免浪费系统资源。 源码下载 总结 值得注意的是,Android下的Service组件也是运行在主线程中的,所以一些Android4.0+无法在主线程上进行的操作,在Service中也必须另外开启线程来完成,如访问网络,还可以使用继承Service的子类IntentService来实现,这个内容会在之后的博客中介绍。Android系统本身还提供了大量的Service组件,开发人员可以通过这些系统Service来操作Android系统本身,这不属于本篇博客的范畴,以后再慢慢详解。 本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/Android_Service1.html,如需转载请自行联系原作者

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

6 docker网络基础配置

一、从外部访问容器应用 1、端口映射实现访问容器 root@docker-test:~# docker run -d -P training/webapp python app.py 61975c6a1981e829a7edb8e07d24c849aad7132c80e14338e6aaab4d12d25021 root@docker-test:~# docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 61975c6a1981 training/webapp:latest "python app.py" 8 seconds ago Up 7 seconds 0.0.0.0:32783->5000/tcp furious_pasteur 大写的-P。会随机映射一个49000-49900的端口至容器内部开放的网络端口 小写的-p,则指定固定端口 上面的ps -l看出,本地的32783端口被映射到了容器的5000端口,访问宿主机的32783端口即可访问容器内web应用提供界面 通过我宿主机的IP地址进行访问 http://192.168.89.130:32783/ 2、通过docker logs查看应用的信息 root@docker-test:~# docker logs -f furious_pasteur * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 192.168.89.1 - - [12/Aug/2017 12:58:34] "GET / HTTP/1.1" 200 - 192.168.89.1 - - [12/Aug/2017 12:58:35] "GET /favicon.ico HTTP/1.1" 404 - 192.168.89.1 - - [12/Aug/2017 12:59:56] "GET / HTTP/1.1" 200 - 3、映射所有接口地址 将本地的5000端口映射到容器的5000端口 docker run -d -p 5000:5000 training/webapp python app.py #此时会绑定本地所有接口上的所有地址 4、映射到指定地址的指定端口 docker run -d -p 192.168.89.130:5000:5000 training/webapp python app.py 5、映射到指定地址的任意端口 docker run -d -p 192.168.89.130::5000 training/webapp python app.py 6、查看映射端口配置 root@docker-test:~# root@docker-test:~# docker port testweb 5000/tcp -> 0.0.0.0:32782 root@docker-test:~# docker port web 5000/tcp -> 0.0.0.0:32781 root@docker-test:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 61975c6a1981 training/webapp:latest "python app.py" 14 minutes ago Up 14 minutes 0.0.0.0:32783->5000/tcp furious_pasteur 235a7f166a79 training/webapp:latest "/bin/bash" 33 minutes ago Up 33 minutes 0.0.0.0:32782->5000/tcp testweb 6c498fba9a26 training/webapp:latest "/bin/bash" 40 minutes ago Up 40 minutes 0.0.0.0:32781->5000/tcp web 39d71abc194d ubuntu:latest "/bin/bash" About an hour ago Up About an hour db2 593de70961a0 ubuntu:latest "/bin/bash" About an hour ago Up About an hour db1 a6a32f7838ee ubuntu:latest "/bin/bash" About an hour ago Up About an hour dbdata root@docker-test:~# docker port 61975c6a1981 5000/tcp -> 0.0.0.0:32783 root@docker-test:~# 二、自定义容器命名 1、自定义容器命名 root@docker-test:~# docker run -d -P --name web training/webapp python app.py #使用--name选项 2、查看设定后的命名 root@docker-test:~# docker ps -l 3、使用inspect查看指定容器ID的容器的名字 root@docker-test:~# docker inspect -f "` `.`Name `" 382b382521b5 二、容器互联(实现容器间通信) 使用--link参数可以让容器之间安全的进行交互 创建一个新的数据库容器进行演示 1、创建并运行数据库容器,名称为db root@docker-test:~# docker run -d --name db training/postgres #如本地没有training/postgres镜像,则会自动从docker hub搜索到镜像并下载 2、创建完成之后查看一下 root@docker-test:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 19f67a71ac16 training/postgres:latest "su postgres -c '/us 2 minutes ago Up 2 minutes 5432/tcp db 3、然后创建一个新的web容器,并将它连接到db容器 root@docker-test:~# docker run -d -P --name web --link db:db training/webapp python app.py 3ac18b1df0d487c99b0f07e2fd273c53ad7b6f5beb29b830985c89fd6df40241 4、查看创建的两个docker容器(web容器和db容器) root@docker-test:~# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3ac18b1df0d4 training/webapp:latest "python app.py" 6 seconds ago Up 4 seconds 0.0.0.0:32769->5000/tcp web 651b10778678 training/postgres:latest "su postgres -c '/us 2 minutes ago Up 2 minutes 5432/tcp db 本文转自 TtrToby 51CTO博客,原文链接:http://blog.51cto.com/freshair/1958350

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

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等操作系统。

用户登录
用户注册