首页 文章 精选 留言 我的

精选列表

搜索[快速入门],共10000篇文章
优秀的个人博客,低调大师

进程管理利器Supervisor--入门简介

目录 概述 Supervisor是什么 Supervisor意图 Supervisor特性 Supervisor组件 平台需求 概述 项目运行需要后台运行,一般都是使用 nohup,但是nohup不能对后台进程监控和失败重启等高级功能,有木有更好的工具可以帮我们做这些事呢,通过谷哥的绑住找到了一个满意答案就是Supervisor 转帖请注明出处:https://my.oschina.net/u/2342969/blog/2963930 Supervisor是什么 Supervisor是一个进程管理系统(其实是一个软件),它有一个可视化界面可以启动进程,查看进程状态,它允许用户监视和控制类unix操作系统上的许多进程。 它与launchd、daemontools和runit等程序共享一些相同的目标。与某些程序不同,它不打算作为init的替代程序“process id 1”运行。相反,它被用于控制与项目或客户相关的过程,并且在引导时像其他程序一样启动。 Supervisor意图 简便 rc.d脚本是流程初始化/自动启动/管理的一种很好的、最基本的形式,但是编写和维护它们可能会很麻烦。此外,rc.d脚本不能自动重启崩溃的进程,许多程序在崩溃时不能正确重启自己。Supervisor将进程作为子进程启动,并且可以配置为在崩溃时自动重启它们。它还可以自动配置为在自己的调用上启动进程。 精准 通常很难在UNIX上准确地获得进程的运行/停止状态。Pidfiles表现是不准确的。Supervisor以子进程的形式启动进程,因此它总是知道其子进程的真正运行/停止状态,并且可以方便地查看这些数据。 托管 我们不希望或不需要完整的shell访问进程运行的机器。在底层TCP端口上侦听的进程通常需要作为根用户启动和重新启动(UNIX的一个错误特性)。通常情况下,允许普通用户停止或重启这样的进程是完全可以的,但是为他们提供shell访问通常是不切实际的,而为他们提供根访问或sudo访问通常是不可能的。向他们解释为什么会存在这个问题也是困难的。如果将Supervisor作为根用户启动,就有可能允许普通用户控制此类流程,而不需要向他们解释问题的复杂性。通过从一个简单的shell或web UI发出“stop”、“start”和“restart”命令,Supervisorctl允许对机器进行非常有限的访问,基本上允许用户查看进程状态并控制受监视控制的子进程。 进程组 Supervisor通过进程组管理进程,进程常常需要在组中启动和停止,甚至可以按“优先顺序”启动和停止。Supervisor允许您为进程分配优先级,并允许用户通过监控管理客户端发出“start all”和“restart all”等命令,这些命令按照预先分配的优先级顺序启动进程。此外,可以将流程分组为“流程组”,并且可以作为一个单元停止和启动一组逻辑相关的流程。 Supervisor特性 简单 Supervisor是通过一个简单的ini风格的配置文件来配置的,很容易学习。它提供了许多进程选项,使您的工作更容易,例如重新启动失败的进程和自动日志循环。 一站式 Supervisor提供了一个开始、停止和监视流程的控制台。进程可以单独控制,也可以分组控制。可以通过配置Supervisor提供本地或远程命令行和web界面。 高效 Supervisor通过fork/exec启动它的子进程,而不是守护。当进程终止时,操作系统立即向Supervisor发出信号,这与某些解决方案不同,这些解决方案依赖于容易出错的的PID文件和定期轮询来重启失败的进程。 可扩展 Supervisor有一个简单的事件通知协议,用任何语言编写的程序都可以使用它来监视它,还有一个XML-RPC接口用于控制。它也可以由Python开发人员利用扩展点构建。 兼容性 Supervisor除了windows系统,其他系统均可以使用。它在Linux、Mac OS X、Solaris和FreeBSD上均得到了测试和支持。它完全用Python编写,所以安装不需要C编译器。 可靠 虽然Supervisor在今天被非常积极的开发,但是它并不是一个新的软件。Supervisor已经存在多年,并且已经在许多服务器上使用。 Supervisor组件 supervisord Supervisor服务部分叫做Supervisord。它负责自己调用时启动子程序,响应来自客户机的命令,重新启动崩溃或退出的子进程,记录子进程挂掉和崩溃的输出,并生成和处理与子进程生命周期中的点对应的“事件”。 它使用了一个配置文件。配置文件通常位于/etc/supervision.conf中。这个配置文件是一个“Windows-INI”风格的配置文件。通过适当的文件系统权限保持该文件的安全性非常重要,因为它可能包含未加密的用户名和密码。 通俗点讲就是Supervisor的处理器 supervisorctl supervisorctl是Supervisor命令行客户端.它提供了一个类shell的接口,用于管理Supervisor提供的特性.用户可以连接到不同的监控器进程(一次一个),获取受控子进程的状态,停止和启动的子进程,以及监控器的运行进程列表。 通俗点讲就是Supervisor的命令工具 Web Server 如果配置中启动了这个模块,就可以通过浏览器访问具有与supervisorctl类似功能的web用户界面。在配置文件的[inet_http_server]部分开启,访问服务器URL(例如http://localhost:9001/),通过web接口查看和控制进程状态。 通俗点讲就是一个可视化界面,可以在界面操作进程 XML-RPC Interface web UI基于XML-RPC接口服务,该接口可用于询问和控制Supervisor及其运行的程序 平台需求 Supervisor经过测试,可以在Linux (Ubuntu 9.10)、Mac OS X(10.4/10.5/10.6)、Solaris (10 for Intel)和FreeBSD 6.1上运行。它在大多数UNIX系统上都可以很好地工作。但是他不能在windows平台下运行 Supervisor可以使用Python 2.4或更高版本,但不能在Python 3的任何版本下工作。

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

My Baits入门(一)mybaits环境搭建

1)在工程下引入mybatis-3.4.1.jar包,再引入数据库(mysql,mssql..)包. 2)在src下新建一个配置文件conf.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 引入外部配置文件 --> <properties resource="jdbc.properties" /> <!-- 配置mybatis运行环境 --> <environments default="development"> <environment id="development"> <!-- type="JDBC" 代表使用JDBC的提交和回滚来管理事务 --> <transactionManager type="JDBC" /> <!-- mybatis提供了3种数据源类型,分别是:POOLED,UNPOOLED,JNDI --> <!-- POOLED 表示支持JDBC数据源连接池 --> <!-- UNPOOLED 表示不支持数据源连接池 --> <!-- JNDI 表示支持外部数据源连接池 --> <dataSource type="POOLED"> <property name="driver" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </dataSource> </environment> </environments> <mappers> <mapper resource="userMapper.xml"/> </mappers> </configuration> 这里是通过外部配置文件来存储数据库存信息的,所以加入一个jdbc.properties的数据库存信息 driver=com.microsoft.sqlserver.jdbc.SQLServerDriver url=jdbc:sqlserver://127.0.0.1;databaseName=test username=sa password=123456 3)建立一个映射文件 userMapper.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="hw.com.ser.IUser"> <!-- 查询全部用户 --> <select id="queryUsers" resultType="hw.com.pojo.User"> select * from MS_User </select> <selectid="queryUserById" resultType="hw.com.pojo.User" parameterType="int"> Select * From Ms_User Where id=#{id} </select> </mapper> (这里要注意的是,namespace属性,因为,此实例是通过接口映射的方式,所以,namespace属性一点要写成接口的路径)附图: 4)建一个映射接口类 package hw.com.ser; import java.util.List; import hw.com.pojo.User; public interface IUser { public List<User> queryUsers(); public User queryUserById(int id); } 5)建立一个SqlSessionFactory package hw.com.util; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.util.Properties; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class SqlSessionFactoryUtil { private static SqlSessionFactory sqlSessionFactory = null; private static final Class CLASS_LOCK = SqlSessionFactoryUtil.class; private SqlSessionFactoryUtil() { } public static SqlSessionFactory initSqlSessionFactory() { String resource = "conf.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { e.printStackTrace(); } synchronized (CLASS_LOCK) { if (sqlSessionFactory == null) { sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } } return sqlSessionFactory; } public static SqlSession openSqlSession(){ if(sqlSessionFactory==null){ initSqlSessionFactory(); } return sqlSessionFactory.openSession(); } } 6)建一个pojo package hw.com.pojo; import java.util.Date; public class User { private String Id; private String UserName; private String UserPwd; private int DeptmentId; private String UserTrueName; private String Email; private int LearnCenterId; private Date CreateDate; private Date LastModifyDate; private int UserStatus; public User() { super(); // TODO Auto-generated constructor stub } public String getId() { return Id; } public void setId(String id) { Id = id; } public String getUserName() { return UserName; } public void setUserName(String userName) { UserName = userName; } public String getUserPwd() { return UserPwd; } public void setUserPwd(String userPwd) { UserPwd = userPwd; } public int getDeptmentId() { return DeptmentId; } public void setDeptmentId(int deptmentId) { DeptmentId = deptmentId; } public String getUserTrueName() { return UserTrueName; } public void setUserTrueName(String userTrueName) { UserTrueName = userTrueName; } public String getEmail() { return Email; } public void setEmail(String email) { Email = email; } public int getLearnCenterId() { return LearnCenterId; } public void setLearnCenterId(int learnCenterId) { LearnCenterId = learnCenterId; } public Date getCreateDate() { return CreateDate; } public void setCreateDate(Date createDate) { CreateDate = createDate; } public Date getLastModifyDate() { return LastModifyDate; } public void setLastModifyDate(Date lastModifyDate) { LastModifyDate = lastModifyDate; } public int getUserStatus() { return UserStatus; } public void setUserStatus(int userStatus) { UserStatus = userStatus; } @Override public String toString() { return "User [Id=" + Id + ", UserName=" + UserName + ", UserPwd=" + UserPwd + ", DeptmentId=" + DeptmentId + ", UserTrueName=" + UserTrueName + ", Email=" + Email + ", LearnCenterId=" + LearnCenterId + ", CreateDate=" + CreateDate + ", LastModifyDate=" + LastModifyDate + ", UserStatus=" + UserStatus + "]"; } } 7) 在main方法下做测试 package hw.com.Day1.main; import java.util.List; import org.apache.ibatis.session.SqlSession; import hw.com.pojo.User; import hw.com.ser.IUser; import hw.com.util.SqlSessionFactoryUtil; public class UserTest { public static void main(String[] args) { SqlSession sqlSession=null; try { sqlSession=SqlSessionFactoryUtil.openSqlSession(); IUser iUser=sqlSession.getMapper(IUser.class); List<User> users=iUser.queryUsers(); if(users.size()>0){ for (User user : users) { System.out.println(user.toString()); } } } catch (Exception e) { e.printStackTrace(); } } } 转自:http://www.cnblogs.com/lijianhua/p/6201158.html

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

神经网络基础及Keras入门

神经网络定义 人工神经网络,简称神经网络,在机器学习和认知科学领域,是一种模仿生物神经网络(动物的中枢神经系统,特别是大脑)的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。 为了描述神经网络,我们先从最简单的神经网络讲起,这个神经网络仅由一个“神经元”构成,以下即是这个“神经元”的图示: 可以看出,这个单一“神经元”的输入-输出映射关系其实就是一个逻辑回归(logistic regression)。 神经网络模型 所谓神经网络就是将许多个单一“神经元”联结在一起,这样,一个“神经元”的输出就可以是另一个“神经元”的输入。例如,下图就是一个简单的神经网络: Keras实战 使用keras实现如下网络结构, 并训练模型: 输入值(x1,x2,x3)代表人的身高体重和年龄, 输出值(y1,y2) importnumpyasnp #总人数是1000,一半是男生 n=1000 #所有的身体指标数据都是标准化数据,平均值0,标准差1 tizhong=np.random.normal(size=n) shengao=np.random.normal(size=n) nianling=np.random.normal(size=n) #性别数据,前500名学生是男生,用数字1表示 gender=np.zeros(n) gender[:500]=1 #男生的体重比较重,所以让男生的体重+1 tizhong[:500]+=1 #男生的身高比较高,所以让男生的升高+1 shengao[:500]+=1 #男生的年龄偏小,所以让男生年龄降低1 nianling[:500]-=1 创建模型 fromkerasimportSequential fromkeras.layersimportDense,Activation model=Sequential() #只有一个神经元,三个输入数值 model.add(Dense(4,input_dim=3,kernel_initializer='random_normal',name="Dense1")) #激活函数使用softmax model.add(Activation('relu',name="hidden")) #添加输出层 model.add(Dense(2,input_dim=4,kernel_initializer='random_normal',name="Dense2")) #激活函数使用softmax model.add(Activation('softmax',name="output")) 编译模型 需要指定优化器和损失函数: model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) 训练模型 #转换成one-hot格式 fromkerasimportutils gender_one_hot=utils.to_categorical(gender,num_classes=2) #身体指标都放入一个矩阵data data=np.array([tizhong,shengao,nianling]).T #训练模型 model.fit(data,gender_one_hot,epochs=10,batch_size=8) 输出(stream): Epoch1/10 1000/1000[==============================]-0s235us/step-loss:0.6743-acc:0.7180 Epoch2/10 1000/1000[==============================]-0s86us/step-loss:0.6162-acc:0.7310 Epoch3/10 1000/1000[==============================]-0s88us/step-loss:0.5592-acc:0.7570 Epoch4/10 1000/1000[==============================]-0s87us/step-loss:0.5162-acc:0.7680 Epoch5/10 1000/1000[==============================]-0s89us/step-loss:0.4867-acc:0.7770 Epoch6/10 1000/1000[==============================]-0s88us/step-loss:0.4663-acc:0.7830 Epoch7/10 1000/1000[==============================]-0s87us/step-loss:0.4539-acc:0.7890 Epoch8/10 1000/1000[==============================]-0s86us/step-loss:0.4469-acc:0.7920 Epoch9/10 1000/1000[==============================]-0s88us/step-loss:0.4431-acc:0.7940 Epoch10/10 1000/1000[==============================]-0s88us/step-loss:0.4407-acc:0.7900 输出(plain)://Python学习开发705673780 进行预测 test_data=np.array([[0,0,0]]) probability=model.predict(test_data) ifprobability[0,0]>0.5: print('女生') else: print('男生') ### 输出(stream): 女生 关键词解释 input_dim: 输入的维度数 kernel_initializer: 数值初始化方法, 通常是正太分布 batch_size: 一次训练中, 样本数据被分割成多个小份, 每一小份包含的样本数叫做batch_size epochs: 如果说将所有数据训练一次叫做一轮的话。epochs决定了总共进行几轮训练。 optimizer: 优化器, 可以理解为求梯度的方法 loss: 损失函数, 可以理解为用于衡量估计值和观察值之间的差距, 差距越小, loss越小 metrics: 类似loss, 只是metrics不参与梯度计算, 只是一个衡量算法准确性的指标, 分类模型就用accuracy 看完觉得有所收获的朋友可以点赞加关注哦,谢谢支持!

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

Java入门系列-22-IO流

File类的使用 Java程序如何访问文件?通过 java.io.File 类 使用File类需要先创建文件对象 File file=new File(String pathname);,创建时在构造函数中指定物理文件或目录,然后通过文件对象的方法操作文件或目录的属性。 \ 是特殊字符,要使用需要转义 \\ File 类常用方法 方法名称 说明 boolean exists() 判断文件或目录是否存在 boolean isFile() 判断是否是文件 boolean isDirectory() 判断是否是目录 String getPath() 返回此对象表示的文件的相对路径名 String getAbsolutePath() 返回此对象表示的文件的绝对路径 String getName() 返回此对象指定的文件或目录 boolean createNewFile() 创建名称的空文件,不创建文件夹 long length() 返回文件的长度,单位为字节,文件不存在则返回0L File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。 static File[] listRoots() 列出可用文件系统根 boolean mkdirs() 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。 使用示例: import java.io.File; import java.io.IOException; public class TestFile { public static void main(String[] args) { //创建File对象 传入文件的路径 File file=new File("D:\\a.txt"); //创建File对象 传入文件夹的路径 File dir=new File("D:/word"); //判断是否存在 if(file.exists()) { if(file.isFile()) { //getName()获取名字 System.out.println(file.getName()+" 是文件"); }else if(file.isDirectory()){ System.out.println(file.getName()+" 是目录"); } }else { System.out.println(file.getName()+" 不存在!"); try { //创建文件 file.createNewFile(); System.out.println("文件大小:"+file.length()+" 字节"); } catch (IOException e) { e.printStackTrace(); } } if(dir.exists()) { if(dir.isFile()) { System.out.println(dir.getName()+" 是文件"); }else if(dir.isDirectory()) { System.out.println(dir.getName()+" 是文件夹"); //绝对路径 System.out.println(dir.getAbsolutePath()); } }else { System.out.println(dir.getName()+" 不存在!"); //创建目录 dir.mkdirs(); } } } 流 流:指一连串流动的字符,是以先进先出方式发送信息的通道 输入流:源数据流向程序(读) 输入流:程序中的数据流向目标数据源(写) Java流的分类 按流向 输出流(OutputStream和Writer作为基类) 输入流(InputStream和Reader作为基类) 输入输出流是相对于计算机内存来说的 按照处理数据单元划分 字节流 字节输入流(InputStream基类) 字节输出流(OutputStream基类) 字符流 字符输入流(Reader基类) 字符输出流(Writer基类) 字节流是8位(1B)通用字节流,字符流是16位(2B)Unicode字符流 字节流 FileInputStream 是 InputStream 的子类 InputStream 类常用方法 方法名称 说明 int read() 从输入流中读取数据的下一个字节。返回0到255的int值,如果到达流的末尾,则返回-1 int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。返回读入缓冲区的总字节数,如果达到末尾则返回-1 int read(byte[] b,int off,int len) 将输入流中最多 len 个数据字节读入 byte数组 void close() 关闭此输入流并释放与该流关联的所有系统资源 int available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取的估计字节数 FileInputStream 类常用构造方法 名称 说明 FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。 使用 FileInputStream 读取文件 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; public class TestFileInputStream { public static void main(String[] args) { FileInputStream fis=null; try { fis=new FileInputStream("D:\\a.txt"); //读取结果存入StringBuffer StringBuffer sb=new StringBuffer(); System.out.println("预计读取:"+fis.available()+"字节"); //记录每次读取的长度 int len=0; //缓冲区字节数组 byte[] buff=new byte[1024]; while((len=fis.read(buff))!=-1) { System.out.println("还剩余:"+fis.available()+"字节"); sb.append(new String(buff,0,len)); } System.out.println("结果:"); System.out.println(sb); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (fis!=null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } } FileOutputStream 是 OutputStream 的子类 OutputStream 类常用方法 方法名称 说明 void write(int c) 将制定的字节写入此输出流 void write(byte[] buf) 将 b.length 个字节从指定的 byte 数组写入此输入流 void write(byte[] b,int off,int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流 void close() 关闭此输出流并释放与此流有关的所有系统资源 FileOutputStream的构造方法 名称 说明 FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流 FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流 FileOutputStream(String name,boolean append) 第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处 使用 FileOutputStream 写文件 import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class TestFileOutputStream { public static void main(String[] args) { FileOutputStream fos=null; try { //创建输出流对象 fos=new FileOutputStream("D:\\c.txt"); //要输出的字符 String str="hello world 你好"; //将字符串转成字节数组并写入到流中 fos.write(str.getBytes()); //刷新流 fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (fos!=null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 字符流 上面的内容我们看到,字节流不能直接操作字符,所以操作字符用字符流。 FileReader 是 Reader 的子类 Reader 类常用方法 方法名称 说明 int read() 读取单个字符 int read(char[] c) 将字符读入数组 read(char[] c,int off,int len) 将字符读入数组的某一部分 void close() 关闭该流并释放与之关联的所有资源 使用 FileReader 读取文本文件 import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; public class TestReader { public static void main(String[] args) { Reader r=null; try { //创建FileReader对象 r=new FileReader("D:\\a.txt"); //字符缓冲数组 char[] chrs=new char[512]; //记录每次读取的个数 int len=0; //循环读取 while((len=r.read(chrs))!=-1) { String str=new String(chrs, 0, len); System.out.println(str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (r!=null) { try { r.close(); } catch (IOException e) { e.printStackTrace(); } } } } } FileWriter 是 Writer 的子类 Writer 类常用方法 方法名称 说明 write(String str) 写入字符串 write(String str,int off,int len) 写入字符串的某一部分 void close() 关闭此流,但要先刷新它 void flush 刷新该流的缓冲 使用 FileWriter 写入文本文件 import java.io.FileWriter; import java.io.IOException; import java.io.Writer; public class TestWriter { public static void main(String[] args) { Writer w=null; try { //创建字符输出流 w=new FileWriter("D:\\msg.txt"); String msg="hello every bady 兄嘚"; //将字符串写入到流中 w.write(msg); w.flush(); } catch (IOException e) { e.printStackTrace(); }finally { if (w!=null) { try { w.close(); } catch (IOException e) { e.printStackTrace(); } } } } } 缓冲字符流 如果频繁的对字符进行读写操作,墙裂建议使用缓冲! BufferedReader 类带有缓冲区,可以先把一批数据读到缓冲区,接下来的读操作都是从缓冲区内获取数据,避免每次都从数据源读取数据进行字符编码转换,从而提高读取操作的效率。 使用BufferedReader读取文本文件 import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class TestBufferedReader { public static void main(String[] args) { FileReader reader=null; BufferedReader br=null; try { //创建字符读入流 reader=new FileReader("D:\\a.txt"); //将字符读入流包装成字符缓冲流 br=new BufferedReader(reader); //记录每行读入的内容 String line=null; //用于拼接保存每行读入的内容 StringBuffer content=new StringBuffer(); while ((line=br.readLine())!=null) { content.append(line+"\n"); } System.out.println("所有内容:"); System.out.println(content); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if (reader!=null) { reader.close(); } if (br!=null) { br.close(); } } catch (Exception e) { e.printStackTrace(); } } } } BufferedReader 是 Reader 的子类,带有缓冲区,特有方法 readLine() 按行读取内容 BufferedWriter 类带有缓冲区,与BufferedReader的方向正好相反,BufferedWriter 是把一批数据写到缓冲区,当缓冲区满的时候,再把缓冲区的数据写到字符输出流中。避免每次都执行物理写操作,提高写操作的效率。 使用 BufferedWriter 写文件 import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class TestBufferedWriter { public static void main(String[] args) { FileWriter writer=null; BufferedWriter bw=null; try { writer=new FileWriter("D:\\out.txt"); bw=new BufferedWriter(writer); bw.write("hello"); //内容换行 bw.newLine(); bw.write("world"); } catch (IOException e) { e.printStackTrace(); }finally { try { if (bw!=null) { bw.close(); } if (writer!=null) { writer.close(); } } catch (IOException e) { e.printStackTrace(); } } } } 关闭流的顺序与创建流的顺序相反 数据流 DataInputStream 类 FileInputStream 的子类 与 FileInputStream 类结合使用读取二进制文件 DataOutputStream 类 FileOutputStream 的子类 与 FileOutputStream 类结合使用写二进制文件 使用数据流复制图片 import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class TestCopy { public static void main(String[] args) { //文件输入流 FileInputStream fis=null; //数据输入流(包装fis得到) DataInputStream dis=null; //文件输出流 FileOutputStream fos=null; //数据输出流(包装fos得到) DataOutputStream dos=null; try { fis=new FileInputStream("D:\\a.jpg"); dis=new DataInputStream(fis); fos=new FileOutputStream("F:\\b.jpg"); dos=new DataOutputStream(fos); //缓冲数组 byte[] buff=new byte[1024]; //记录每次读取的字节个数 int len=0; //循环读入 while((len=dis.read(buff))!=-1) { //循环写入len个字节 dos.write(buff,0,len); } System.out.println("完成"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { if (dis!=null) { dis.close(); } if (dos!=null) { dos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }

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

Docker安装gitlab从入门到放弃

运行镜像: [root@sannian min]# docker run -d --restart=always --name gitlab -p 9999:80 -p 4422:22 --hostname 47.99.145.156 twang2218/gitlab-ce-zh [root@sannian .ssh]# ssh-keygen -t rsa -C "admin@example.com" [root@sannian .ssh]# vim /root/.gitconfig [root@sannian .ssh]# vim id_rsa.pub 创建并添加密钥 [root@sannian .ssh]# git clone git@47.99.145.156:4422:root/eatjoys-front-min.git Cloning into 'eatjoys-front-min'... git@47.99.145.156's password: Permission denied, please try again. git@47.99.145.156's password: 结果还是要密码 还密码不对,,,整了三天,问了半天说是22端口问题 ################################################## 然后重新来来,把以前的镜像删除: [root@sannian .ssh]# docker rm -f e9c5ee1d394a 改变运行镜像命令

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

Java入门系列-21-多线程

什么是线程 在操作系统中,一个应用程序的执行实例就是进程,进程有独立的内存空间和系统资源,在任务管理器中可以看到进程。 线程是CPU调度和分派的基本单位,也是进程中执行运算的最小单位,可完成一个独立的顺序控制流程,当然一个进程中可以有多个线程。 多线程:一个进程中同时运行了多个线程,每个线程用来完成不同的工作。多个线程交替占用CPU资源,并非真正的并行执行。 使用多线程能充分利用CPU的资源,简化编程模型,带来良好的用户体验。 一个进程启动后拥有一个主线程,主线程用于产生其他子线程,而且主线程必须最后完成执行,它执行各种关闭动作。 在Java中main()方法为主线程入口,下面使用 Thread 类查看主线程名。 public class MainThread { public static void main(String[] args) { //获取当前线程 Thread t=Thread.currentThread(); System.out.println("当前线程名字:"+t.getName()); //自定义线程名字 t.setName("MyThread"); System.out.println("当前线程名字:"+t.getName()); } } 创建线程 在Java中创建线程有两种方式 1.继承 java.lang.Thread 类 2.实现 java.lang.Runnable 接口 1.继承 Thread 类创建线程 (1)定义MyThread类继承Thread类 (2)重写run()方法,编写线程执行体 public class MyThread extends Thread{ //重写run方法 @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } (3)创建线程对象,调用start()方法启动线程 public class TestMyThread { public static void main(String[] args) { MyThread myThread=new MyThread(); //启动线程 myThread.start(); } } 多个线程同时启动后是交替执行的,线程每次执行时长由分配的CPU时间片长度决定 修改 TestMyThread.java 观察多线程交替执行 public class TestMyThread { public static void main(String[] args) { MyThread myThread1=new MyThread(); MyThread myThread2=new MyThread(); myThread1.start(); myThread2.start(); } } 多运行几次观察效果 启动线程能否直接调用 run()方法? 不能,调用run()方法只会是主线程执行。调用start()方法后,子线程执行run()方法,主线程和子线程并行交替执行。 2.实现 Runnable 接口创建线程 (1)定义MyRunnable类实现Runnable接口 (2)实现run()方法,编写线程执行体 public class MyRunnable implements Runnable{ //实现 run方法 @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println(Thread.currentThread().getName()+":"+i); } } } (3)创建线程对象,调用start()方法启动线程 public class TestMyRunnable { public static void main(String[] args) { Runnable runnable=new MyRunnable(); //创建线程,传入runnable Thread t=new Thread(runnable); t.start(); } } 线程的生命周期 graph LR A(创建状态) -->|启动线程| B(就绪状态) C(阻塞状态) -->|阻塞解除| B D(运行状态) -->|释放CPU资源| B B -->|获得CPU资源| D D -->|等待用户输入线程休眠等| C D --> E(死亡状态) 创建状态:线程创建完成,比如 MyThread thread=new MyThread 就绪状态:线程对象调用 start() 方法,线程会等待CPU分配执行时间,并没有立马执行 运行状态:线程分配到了执行时间,进入运行状态。线程在运行中发生礼让 (yield) 会回到就绪状态 阻塞状态:执行过程中遇到IO操作或代码 Thread.sleep(),阻塞后的线程不能直接回到运行状态,需要重新进入就绪状态等待资源的分配。 死亡状态:自然执行完毕或外部干涉终止线程 线程调度 线程调度指按照特定机制为多个线程分配CPU的使用权 线程调度常用方法 方法 说明 setPriority(int newPriority) 更改线程的优先级 static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠 void join() 等待该线程终止 static void yield() 暂停当前正在执行的线程对象,并执行其他线程 void interrupt() 中断线程 boolean isAlive() 测试线程是否处于活动状态 线程优先级的设置 线程优先级由1~10表示,1最低,默认有限级为5。优先级高的线程获得CPU资源的概率较大。 public class TestPriority { public static void main(String[] args) { Thread t1=new Thread(new MyRunnable(),"线程A"); Thread t2=new Thread(new MyRunnable(),"线程B"); //最大优先级 t1.setPriority(Thread.MAX_PRIORITY); //最小优先级 t2.setPriority(Thread.MIN_PRIORITY); t1.start(); t2.start(); } } 线程休眠 让线程暂时睡眠指定时长,线程进入阻塞状态,睡眠时间过后线程会再进入可运行状态。 休眠时长以毫秒为单位,调用sleep()方法需要处理 InterruptedException异常。 public class TestSleep { public static void main(String[] args) { for (int i = 1; i <= 10; i++) { System.out.println("第 "+i+" 秒"); try { //让当前线程休眠1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } 强制运行 使用 join() 方法实现,可以认为是线程的插队,会先强制执行插队的线程。 public class JoinThread implements Runnable{ @Override public void run() { for (int i = 1; i <=10; i++) { System.out.println("线程名:"+Thread.currentThread().getName()+" i:"+i); } System.out.println("插队线程执行完毕!"); } } public class TestJoin { public static void main(String[] args) { Thread joinThread=new Thread(new JoinThread(),"插队的线程"); //启动后与主线程交替执行 joinThread.start(); for (int i = 1; i <= 10; i++) { if (i==5) { try { System.out.println("====开始插队强制执行===="); joinThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("线程名:"+Thread.currentThread().getName()+" i:"+i); } System.out.println("主线程执行完毕!"); } } 最一开始执行,主线程 main 和 "插队的线程"是交替执行。当主线程的循环到第5次的时候,调用 "插队的线程"的join方法,开始强制执行"插队的线程",待"插队的线程"执行完后,才继续恢复 main 线程的循环。 线程礼让 使用 yield() 方法实现,礼让后会暂停当前线程,转为就绪状态,其他具有相同优先级的线程获得运行机会。 下面我们实现Runnable接口,在run方法中实现礼让,创建两个线程,达到某种条件时礼让。 public class YieldThread implements Runnable{ @Override public void run() { for (int i = 1; i <= 10; i++) { System.out.println("线程名:"+Thread.currentThread().getName()+" i:"+i); //当前线程执行到5后发生礼让 if (i==5) { System.out.println(Thread.currentThread().getName()+" 礼让:"); Thread.yield(); } } } } public class TestYield { public static void main(String[] args) { Thread t1=new Thread(new YieldThread(),"A"); Thread t2=new Thread(new YieldThread(),"B"); t1.start(); t2.start(); } } 只是提供一种可能,不能保证一定会实现礼让 线程同步 首先看一个多线共享同一个资源引发的问题 仓库有10个苹果,小明、小红、小亮每次可以从仓库中拿1个苹果,拿完苹果后仓库中的苹果数量-1。 先编写仓库资源类,实现接口 //这个实现类将被多个线程对象共享 public class ResourceThread implements Runnable{ private int num=10; @Override public void run() { while(true) { if (num<=0) { break; } num--; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿走一个,还剩余:"+num); } } } 编写测试类,创建两个线程对象,共享同一个资源 public class TestResource { public static void main(String[] args) { ResourceThread resource=new ResourceThread(); //使用同一个Runnable实现类对象 Thread t1=new Thread(resource,"小明"); Thread t2=new Thread(resource,"小红"); Thread t3=new Thread(resource,"小亮"); t1.start(); t2.start(); t3.start(); } } 运行后我们发现,每次拿完苹果后的剩余数量出现了问题,使用同步方法可以解决这个问题。 语法: 访问修饰符 synchronized 返回类型 方法名(参数列表){ …… } synchronized 就是为当前的线程声明一个锁 修改 ResourceThread.java 实现同步 //这个实现类将被多个线程对象共享 public class ResourceThread implements Runnable{ private int num=10; private boolean isHave=true; @Override public void run() { while(isHave) { take(); } } //同步方法 public synchronized void take() { if (num<=0) { isHave=false; return; } num--; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿走一个,还剩余:"+num); } } 实现同步的第二种方式同步代码块 语法: synchronized(syncObject){ //需要同步的代码 } syncObject为需同步的对象,通常为this 修改 ResourceThread.java 改为同步代码块 //这个实现类将被多个线程对象共享 public class ResourceThread implements Runnable{ private int num=10; private boolean isHave=true; @Override public void run() { while(isHave) { synchronized(this) { if (num<=0) { isHave=false; return; } num--; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"拿走一个,还剩余:"+num); } } } }

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

Java入门系列-12-成员方法

类的方法 无参方法 语法: public 返回值类型 方法名(参数列表){ //方法的主体 } 敲一敲:无返回值方法 public void sayHi(){ System.out.println("你好"); } 没有返回值返回值类型为 void ,上例中是无返回值。如果方法中有返回值,方法中必须使用关键之 return 返回该值,返回值类型为该返回值的类型。 敲一敲:有返回值方法 public class Student { String name; int age; /** * 获取年龄 * @return */ public int getAge() { return age; } /** * 获取名字 * @return */ public String getName() { return name; } } 敲一敲:调用有返回值方法 public class Main { public static void main(String[] args) { Student stu=new Student(); stu.age=10; stu.name="张三"; //调用有参方法1 直接接收返回值 int age=stu.getAge(); System.out.println("年龄:"+age); //调用有参方法2 有返回的方法作为一个元素使用 String hello="大家好,我是:"+stu.getName(); System.out.println(hello); System.out.println(stu.getName()); } } 有参方法 定义带参方法的语法: <访问修饰符> 返回类型 <方法名>(<形式参数列表>){ 方法的主体 } 参数允许设置多个,声明时使用的参数叫做形参,调用时实际传入的值叫做实参。 调用方法,参数的参数要与参数列表一一对应。 敲一敲:带参方法的定义和调用 public class DemoMethod { public void sayFriend(String name1,int num) { System.out.println(name1+" 有 "+num+" 个好朋友!"); } public static void main(String[] args) { DemoMethod method=new DemoMethod(); String name="张三";//实参 int num=2; method.sayFriend(name, num);//注意顺序 } } 数组和对象也可以作为参数敲一敲: public class DemoParam { /** * 模拟Arrays.toString()方法,打印数组 * @param names */ public void showArray(String[] names) { System.out.print("["); for (int i = 0; i < names.length; i++) { System.out.print(names[i]); if (i<names.length-1) { System.out.print(","); } } System.out.println("]"); System.out.println(); } public static void main(String[] args) { String[] names= {"张三","李四"}; DemoParam demo=new DemoParam(); demo.showArray(names); } } 成员变量和局部变量 变量声明的位置不同,作用域也不同,作用域可以确定变量可以在哪些区域访问。直接声明在类中的是成员变量,声明在方法中的是局部变量。 敲一敲:感受局部变量和成员变量 public class Student { String name="李四";//成员变量 int age=29;//成员变量 /** * 获取年龄 * @return */ public int getAge() { int age=10;//局部变量 return age; } /** * 获取名字 * @return */ public String getName() { int age=20;//局部变量 return name; } public static void main(String[] args) { Student stu=new Student(); System.out.println("年龄:"+stu.getAge());//10 System.out.println("名字:"+stu.getName()); } } 成员变量在所有实例方法中都可以访问 局部变量只能在当前声明的方法中使用,多个方法可以声明相同名字的局部变量 局部变量和成员变量名字相同时,当前方法中优先使用局部变量 java 会给成员变量一个初始值,不会给局部变量初始值 包 JDK中有大量的类,其中也不乏一些同名的类,那JDK是怎么区分这些同名的类的?使用包可以解决这个问题。 语法: package 包名;//声明包 import 包名;//导入包 public class 类名{ 成员变量 方法 …… } 声明一个类所在的名使用 package 关键字,package 一定要再所有语句中第一行,且只有一个。 使用某个包中的类使用 import 关键字,可以写多个,写在 package 的下面,声明类的上面。 导入包时可以使用完全限定名,如 import java.util.Date;,或者包中的所有类如 import java.util.*; 包和目录的关系:创建包 com.jikedaquan 相当于创建了目录结构 comjikedaquan 包命名规范:包名由小写字母组成,不能以圆点开头或结尾。包名之前最好加上唯一的额前缀,通常使用组织倒置的网络域名如www.jikedaquan.com的包名为 com.jikedaquan,包名后续部分依不同机构内部的规范不同而不同。 另请搜索 在 eclipse 中创建包,本文章不在细述。 搜索关注公众号「享智同行」,第一时间获取技术干货

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

Java入门系列-09-循环结构

这篇文章为你搞懂5个问题 while 循环如何使用 do-while 循环的使用 for 循环的使用 break、continue 的使用 循环结构的嵌套使用 生活中有很多事情需要我们重复的去做,比如围着操场跑10圈,比如写了个爬虫需要爬取20个页面,这些都是循环。 while 循环 while 循环是一个先判断后执行的循环,由循环条件和循环操作组成。 语法: while(循环条件){ 循环操作 } 敲一敲: public class DemoWhile { public static void main(String[] args) { int i=0;//定义一个变量 while(i<10) {//循环条件 System.out.println(i); i++;//更新条件 } } } 循环条件为 true 时执行循环操作,为 false 时不执行 上面的代码中的循环条件是i小于10,由于i最开始时为0所以比较结果为true,进入循环,在循环操作中修改变量的值,使条件不断更新,防止死循环,当i的值为10的时,循环条件为 false,这时候循环就结束了。 敲一敲: /** * 计算 1-100的和 * @author Jack * */ public class DemoSum { public static void main(String[] args) { int sum=0;//定义保存和的变量 int i=1;//要更新的数字 while(i<=100) {//循环1-100 sum+=i;//累加 i++;//更新数字 } System.out.println("1-100的和:"+sum); } } 敲一敲: import java.util.Scanner; /** * 输入y打招呼,输入n结束 * @author Jack * */ public class DemoWhileInput { public static void main(String[] args) { Scanner input=new Scanner(System.in); System.out.println("输入y打招呼,输入n结束"); char choose=input.next().charAt(0); while('y'==choose) {//char类型的比较使用 == System.out.println("hello"); System.out.println("输入y打招呼,输入n结束"); choose=input.next().charAt(0); } System.out.println("循环结束"); } } do-while循环 do-while循环执行的特点是先执行后判断,先执行 do 代码块中的代码,循环条件为 true时继续执行 do 代码块,为 false 时结束循环。 语法: do{ 循环操作 }while(循环条件); 敲一敲: public class DemoDoWhileSum { public static void main(String[] args) { int sum=0;//用于保存求和后的值 int i=1; do { sum+=i; i++; } while (i<=100); System.out.println("1-100的和为:"+sum); } } 上面 while 循环中的打招呼的代码改用 do-while 更合适,下面的代码会先打招呼,然后询问是否继续,输入y将继续 敲一敲: import java.util.Scanner; public class DemoDoWhile { public static void main(String[] args) { Scanner input=new Scanner(System.in); char choose=' '; do { System.out.println("hello"); System.out.println("输入y继续打招呼,输入n结束"); choose=input.next().charAt(0); }while(choose=='y'); System.out.println("循环结束"); } } for 循环 对于固定次数的循环,使用 for 将更加简洁 语法: for(参数初始化;条件判断;更新循环变量){ 循环操作 } 1.先执行参数初始化 2.然后进行条件判断,如果为 true 执行第3步,为 false 将结束循环 3.执行循环操作 4.更新循环变量,然后再次进入第2步进行条件判断 敲一敲: public class DemoFor { public static void main(String[] args) { //打印1-100的数 for(int i=1;i<=100;i++) { System.out.println(i); } } } 参数初始化和更新变量可以同时操作多个变量,像 i++,j-- 这样用 , 隔开 import java.util.Scanner; public class DemoAddTable { public static void main(String[] args) { System.out.println("请输入一个值:"); Scanner input=new Scanner(System.in); int val=input.nextInt(); for(int i=0,j=val;i<=val;i++,j--) { System.out.println(i+" + "+j+"="+(i+j)); } } } 在 for 循环中两个 ; 不能省略 如果省略循环条件将造成死循环 参数初始化可以省略,但要放在循环的上面,保证变量的可用 更新循环变量可以省略,但要放在循环里面,保证变量的更新不会导致死循环 break 和 continue break:改变程序控制流程,用于 do-while、while、for、switch,跳出结构执行结构后面的语句。 敲一敲: import java.util.Scanner; public class DemoBreak { public static void main(String[] args) { Scanner input=new Scanner(System.in); while(true) { System.out.println("是否继续游戏?输入任意继续,输入no结束:"); String goon=input.next(); if ("no".equals(goon)) {//字符串之间的比较使用 equals break; } } System.out.println("结束"); } } 这里的循环条件为 true,也就是一个死循环,但在循环过程中如果输入 no 将执行 break ,那么这个循环也就结束了。 continue:只能用在循环中,跳过循环体中剩余的语句而执行下一次循环。 敲一敲: import java.util.Scanner; /** * 统计年龄大于16的人数 * @author Jack * */ public class DemoContinue { public static void main(String[] args) { Scanner input=new Scanner(System.in); System.out.println("请输入学员数量:"); int pnum=input.nextInt();//学员总人数 int num=0;//保存年龄大于16的人数 for(int i=1;i<=pnum;i++) { System.out.println("请输入第 "+i+" 位学员的年龄:"); int age=input.nextInt(); if (age<17) { continue;//跳过后面代码,继续下一次循环 } num++; } System.out.println("年龄大于16的人数:"+num); } } 循环嵌套 嵌套循环的特点:外层循环执行一次,内层循环执行一遍,各种循环可以任意嵌套,下面使用 for 循环演示打印矩形。语法: while(……){ for(……;……;……){ } } do{ while(……){ } }while(……); for(……;……;……){ do{ }while(……); } …… 敲一敲: import java.util.Scanner; public class DemoRectangle { public static void main(String[] args) { Scanner input=new Scanner(System.in); System.out.println("输入要打印的行数:"); int line=input.nextInt();//行数 System.out.println("输入要打印的列数:"); int column=input.nextInt(); //外层循环控制行数,内层循环控制列数 for (int i = 1; i <= line; i++) { for (int j = 1; j <= column; j++) { System.out.print("* ");//不换行打印 } //打印完所有的列后换行 System.out.println(); } } } 敲一敲: /** * 打印一个三角形 * @author Jack * */ public class DemoDelta { public static void main(String[] args) { for(int i=1;i<=5;i++) {//外层循环控制行 for (int j = 1; j <= i; j++) {//内层循环控制列的条件 System.out.print("* "); } System.out.println(); } } } 打印一个5行的三角形,外层的循环控制行数,所以条件是 i<=5 。列和行的条件是什么?第一行1个,第二行2个,第三行3个*,所以条件为 j<=i 。 试一试 1.使用嵌套循环打印倒三角形 2.使用嵌套循环打印99乘法表 1*1=1 1*2=2 2*2=4 …… 1*8=8 2*8=16 …… 1*9=9 2*9=18 …… 9*9=81 搜索关注公众号「享智同行」,第一时间获取技术干货,关注后回复009 获取本次练习答案!

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

RxJava2 入门详细笔记(2)

六、过滤操作符 6.1、filter() 通过一定逻辑来过滤被观察者发送的事件,如果返回 true 则会发送事件,否则不会发送 Observable.just(1, 2, 3, 4).filter(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer % 2 == 0; } }).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 07:57:48.196 12753-12753/? E/MainActivity: accept : 2 10-06 07:57:48.196 12753-12753/? E/MainActivity: accept : 4 6.2、ofType() 过滤不符合该类型的事件 Observable.just(1, 2, "Hi", 3, 4, "Hello").ofType(Integer.class).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 07:59:41.265 12857-12857/leavesc.hello.rxjavademo E/MainActivity: accept : 1 10-06 07:59:41.265 12857-12857/leavesc.hello.rxjavademo E/MainActivity: accept : 2 10-06 07:59:41.265 12857-12857/leavesc.hello.rxjavademo E/MainActivity: accept : 3 10-06 07:59:41.265 12857-12857/leavesc.hello.rxjavademo E/MainActivity: accept : 4 6.3、skip() 以正序跳过指定数量的事件 Observable.just(1, 2, 3, 4).skip(2).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:01:09.183 12971-12971/leavesc.hello.rxjavademo E/MainActivity: accept : 3 10-06 08:01:09.183 12971-12971/leavesc.hello.rxjavademo E/MainActivity: accept : 4 6.4、skipLast() 以反序跳过指定数量的事件 Observable.just(1, 2, 3, 4).skipLast(2).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:02:00.753 13079-13079/leavesc.hello.rxjavademo E/MainActivity: accept : 1 10-06 08:02:00.753 13079-13079/leavesc.hello.rxjavademo E/MainActivity: accept : 2 6.5、distinct() 过滤事件序列中的重复事件 Observable.just(1, 2, 1, 2, 3, 4, 3).distinct().subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:03:27.402 13189-13189/leavesc.hello.rxjavademo E/MainActivity: accept : 1 10-06 08:03:27.402 13189-13189/leavesc.hello.rxjavademo E/MainActivity: accept : 2 10-06 08:03:27.402 13189-13189/leavesc.hello.rxjavademo E/MainActivity: accept : 3 10-06 08:03:27.402 13189-13189/leavesc.hello.rxjavademo E/MainActivity: accept : 4 6.6、distinctUntilChanged() 过滤掉连续重复的事件 Observable.just(1, 2, 2, 1, 3, 4, 3, 3).distinctUntilChanged().subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:04:44.531 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 1 10-06 08:04:44.541 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 2 10-06 08:04:44.541 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 1 10-06 08:04:44.541 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 3 10-06 08:04:44.541 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 4 10-06 08:04:44.541 13294-13294/leavesc.hello.rxjavademo E/MainActivity: accept : 3 6.7、take() 控制观察者接收事件的数量 Observable.just(1, 2, 2, 1, 3, 4, 3, 3).take(3).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:05:43.520 13397-13397/? E/MainActivity: accept : 1 10-06 08:05:43.520 13397-13397/? E/MainActivity: accept : 2 10-06 08:05:43.520 13397-13397/? E/MainActivity: accept : 2 6.8、debounce() 如果两个事件发送的时间间隔小于设定的时间间隔,则前一件事件不会发送给观察者 Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { emitter.onNext(1); Thread.sleep(900); emitter.onNext(2); } }).debounce(1, TimeUnit.SECONDS).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 10-06 08:08:59.337 13509-13523/leavesc.hello.rxjavademo E/MainActivity: accept : 2 6.9、firstElement() && lastElement() firstElement() 取事件序列的第一个元素,lastElement() 取事件序列的最后一个元素 Observable.just(1, 2, 3, 4, 5).firstElement().subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 6.10、elementAt() & elementAtOrError() elementAt() 可以指定取出事件序列中事件,但是输入的 index 超出事件序列的总数的话就不会触发任何调用,想触发异常信息的话就用 elementAtOrError() Observable.just(1, 2, 3, 4, 5).elementAt(5).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); 以上代码不会触发任何 改用为 elementAtOrError(),则会抛出异常 Observable.just(1, 2, 3, 4, 5).elementAtOrError(5).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept : " + integer); } }); Process: leavesc.hello.rxjavademo, PID: 13948 io.reactivex.exceptions.OnErrorNotImplementedException: The exception was not handled due to missing onError handler in the subscribe() method call. Further reading: https://github.com/ReactiveX/RxJava/wiki/Error-Handling | null at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704) at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701) at io.reactivex.internal.observers.ConsumerSingleObserver.onError(ConsumerSingleObserver.java:46) at io.reactivex.internal.operators.observable.ObservableElementAtSingle$ElementAtObserver.onComplete(ObservableElementAtSingle.java:115) at io.reactivex.internal.operators.observable.ObservableFromArray$FromArrayDisposable.run(ObservableFromArray.java:111) at io.reactivex.internal.operators.observable.ObservableFromArray.subscribeActual(ObservableFromArray.java:37) at io.reactivex.Observable.subscribe(Observable.java:12090) at io.reactivex.internal.operators.observable.ObservableElementAtSingle.subscribeActual(ObservableElementAtSingle.java:37) at io.reactivex.Single.subscribe(Single.java:3438) at io.reactivex.Single.subscribe(Single.java:3424) 七、条件操作符 7.1、all() 判断事件序列是否全部满足某个事件,如果都满足则返回 true,反之则返回 false Observable.just(1, 2, 3, 4, 5).all(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer % 2 == 0; } }).subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { Log.e(TAG, "accept: " + aBoolean); } }); 10-06 08:16:10.212 14043-14043/leavesc.hello.rxjavademo E/MainActivity: accept: false 7.2、takeWhile() 发射原始 Observable,直到指定的某个条件不成立的那一刻,它停止发射原始 Observable,并终止自己的 Observable Observable.just(1, 2, 3, 4, 5, 1, 2).takeWhile(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer < 4; } }).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept: " + integer); } }); 10-06 14:03:42.110 20095-20095/leavesc.hello.rxjavademo E/MainActivity: accept: 1 10-06 14:03:42.110 20095-20095/leavesc.hello.rxjavademo E/MainActivity: accept: 2 10-06 14:03:42.110 20095-20095/leavesc.hello.rxjavademo E/MainActivity: accept: 3 7.3、skipWhile() 订阅原始的 Observable,但是忽略它的发射物,直到指定的某个条件变为 false 时才开始发射原始 Observable Observable.just(1, 2, 4, 1, 3, 4, 5, 1, 5) .skipWhile(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer < 3; } }) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "integer " + integer); } }); 10-06 13:59:40.583 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 4 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 1 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 3 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 4 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 5 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 1 10-06 13:59:40.593 19764-19764/leavesc.hello.rxjavademo E/MainActivity: integer 5 7.4、takeUntil() 用于设置一个条件,当事件满足此条件时,此事件会被发送,但之后的事件就不会被发送了 Observable.just(1, 2, 4, 1, 3, 4, 5, 1, 5) .takeUntil(new Predicate<Integer>() { @Override public boolean test(Integer integer) throws Exception { return integer > 3; } }) .subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "integer " + integer); } }); 10-06 08:54:24.833 17208-17208/? E/MainActivity: integer 1 10-06 08:54:24.833 17208-17208/? E/MainActivity: integer 2 10-06 08:54:24.833 17208-17208/? E/MainActivity: integer 4 7.5、skipUntil() 当 skipUntil() 中的 Observable 发送事件了,原始的 Observable 才会发送事件给观察者 Observable.intervalRange(1, 6, 0, 1, TimeUnit.SECONDS) .skipUntil(Observable.intervalRange(10, 3, 1, 1, TimeUnit.SECONDS)) .subscribe(new Observer<Long>() { @Override public void onSubscribe(Disposable d) { Log.e(TAG, "onSubscribe"); } @Override public void onNext(Long along) { Log.e(TAG, "onNext : " + along); } @Override public void onError(Throwable e) { Log.e(TAG, "onError"); } @Override public void onComplete() { Log.e(TAG, "onComplete"); } }); 10-06 08:51:16.926 16877-16877/leavesc.hello.rxjavademo E/MainActivity: onSubscribe 10-06 08:51:17.946 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onNext : 2 10-06 08:51:18.936 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onNext : 3 10-06 08:51:19.946 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onNext : 4 10-06 08:51:20.936 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onNext : 5 10-06 08:51:21.946 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onNext : 6 10-06 08:51:21.946 16877-16892/leavesc.hello.rxjavademo E/MainActivity: onComplete 7.6、sequenceEqual() 判断两个 Observable 发送的事件是否相同,如果两个序列是相同的(相同的数据,相同的顺序,相同的终止状态),它就发射 true,否则发射 false Observable.sequenceEqual(Observable.just(1, 2, 3), Observable.just(1, 2, 3)) .subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { Log.e(TAG, "accept aBoolean : " + aBoolean); } }); 10-06 08:46:59.369 16492-16492/leavesc.hello.rxjavademo E/MainActivity: accept aBoolean : true 7.7、contains() 判断事件序列中是否含有某个元素,如果有则返回 true,如果没有则返回 false Observable.just(1, 2, 3, 4).contains(2).subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { Log.e(TAG, "accept aBoolean : " + aBoolean); } }); 10-06 08:45:58.100 16386-16386/leavesc.hello.rxjavademo E/MainActivity: accept aBoolean : true 7.8、isEmpty() 判断事件序列是否为空 Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { emitter.onComplete(); } }).isEmpty().subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { Log.e(TAG, "accept aBoolean: " + aBoolean); } }); 10-06 08:43:43.201 16278-16278/leavesc.hello.rxjavademo E/MainActivity: accept aBoolean: true 7.9、amb() amb() 接收一个 Observable 集合,但是只会发送最先发送事件的 Observable 中的事件,不管发射的是一项数据还是一个 onError 或 onCompleted 通知,其余 Observable 将会被丢弃 List<Observable<Long>> list = new ArrayList<>(); list.add(Observable.intervalRange(1, 3, 2, 1, TimeUnit.SECONDS)); list.add(Observable.intervalRange(10, 3, 0, 1, TimeUnit.SECONDS)); Observable.amb(list).subscribe(new Consumer<Long>() { @Override public void accept(Long aLong) throws Exception { Log.e(TAG, "accept: " + aLong); } }); 10-06 08:41:45.783 16053-16068/leavesc.hello.rxjavademo E/MainActivity: accept: 10 10-06 08:41:46.783 16053-16068/leavesc.hello.rxjavademo E/MainActivity: accept: 11 10-06 08:41:47.783 16053-16068/leavesc.hello.rxjavademo E/MainActivity: accept: 12 7.10、defaultIfEmpty() 如果 Observable 没有发射任何值,则可以利用这个方法发送一个默认值 Observable.create(new ObservableOnSubscribe<Integer>() { @Override public void subscribe(ObservableEmitter<Integer> emitter) throws Exception { emitter.onComplete(); } }).defaultIfEmpty(100).subscribe(new Consumer<Integer>() { @Override public void accept(Integer integer) throws Exception { Log.e(TAG, "accept: " + integer); } }); 10-06 08:40:04.754 15945-15945/leavesc.hello.rxjavademo E/MainActivity: accept: 100 更多的学习笔记看这里:Java_Android_Learn

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

Python编程入门基础语法详解经典

一、基本概念 1.内置的变量类型: Python是有变量类型的,而且会强制检查变量类型。内置的变量类型有如下几种: #浮点 float_number=2.3 #复数 complex_number=1+5j #整型 integer_number=1 #list 序列 sample_list=[2,52,36,'abc'] #嵌套 sample_nest=[(2,4,6),{5:7,9:11,'key':[2,5]},6] #dictionary 字典 sample_dic={"key":value, 5:10} #tuple 只读的序列 sample_tuple=(3,9,"ab") 从上面的示例可以看出,python的变量无需声明,可直接给变量赋值。 2.字符串 python中声明一个字符串通常有三种方法,''、" "和''' ''',这三种方法在声明普通字符串时的效果是完全一样的,区别在于字符串本身中存在引号的情况,举例如下: word='good' sentence="hello world" paragraph='''good noon:"nice to meet you."''' python中单行注释采用#开头。 #!/usr/bin/python # First comment print "Hello, world!"; # second comment 上述内容输出:hello,Python!。注释可以在语句或表达式行末。 多行注释可采用三引号,比如: '''This is a comment. This is a comment, too. This is a comment, too. I said that already.''' 转义符 ''; 自然字符串, 通过在字符串前加r或R。 如 r"this is a line with " 则 会显示,并不是换行。 python允许处理unicode字符串,加前缀u或U, 如 u"this is an unicode string"。 3.Python标识符 在python里,标识符有字母、数字、下划线组成。 在python中,所有标识符可以包括英文、数字以及下划线(_),但不能以数字开头。 python中的标识符是区分大小写的。 以下划线开头的标识符是有特殊意义的。以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用"from xxx import *"而导入; 以双下划线开头的(__foo)代表类的私有成员;以双下划线开头和结尾的(__foo__)代表python里特殊方法专用的标识,如__init__()代表类的构造函数。 4.Python保留字符 下面的列表显示了在Python中的保留字。这些保留字不能用作常数或变数,或任何其他标识符名称。 所有Python的关键字只包含小写字母。 如果你在学习Python的过程中遇见了很多疑问和难题,可以加-q-u-n227 -435-450里面有软件视频资料免费 5.行和缩进 学习Python与其他语言最大的区别就是,Python的代码块不使用大括号({})来控制类,函数以及其他逻辑判断。python最具特色的就是用缩进来写模块。 缩进的空白数量是可变的,但是所有代码块语句必须包含相同的缩进空白数量,这个必须严格执行。如下所示: ifTrue: print"True" else: print"False" 上述,if与else的缩进空白数量相同。以下代码将会报错: ifTrue: print"Answer" print "True" else: print "Answer" print"False" python中分号;标识一个逻辑行的结束,但是实际中一般每个物理行只写一个逻辑行,可以避免使用分号。这样书写便于阅读。注意:不要混合使用空格和制表符来缩进,因为在跨越不同的平台时无法正常工作。 多个物理行中可以写一个逻辑行,使用行连接符,如下: s="peteris writing this article" 二、运算符与表达式 1. 运算符与其用法 2. 运算符优先级(从低到高) 三.控制流 1. 条件语句 1.1 if语句 例子, 执行if语句内的程序 a=input("a:") b=input("b:") if(a > b): print a, " > ", b if else语句: a=input("a:") b=input("b:") if(a > b): print a, " > ", b else: print a, " < ", b 1.2 if…elif…else语句 例子:根据输入的分数,输出分数等级: score=raw_input("score:") score=int(score) if(score >=90)and(score <=100): print"A" elif(score >=80)and(score < 90): print"B" elif(score >=60)and(score < 80): print "C" else: print "D" raw_input() 读取输入值。 1.3 if语句的嵌套 编写条件语句时,应该尽量避免使用嵌套语句。嵌套语句不便于阅读,而且可能会忽略一些可能性。 x=-1 y=99 if(x >=0): if(x > 0): #嵌套的if语句 y=1 else: y=0 else: y=-1 print "y =", y 1.4 实现switch语句的功能 python中没有switch特殊字,Python可以通过字典实现switch语句的功能。 实现方法分两步。首先,定义一个字典。字典是由键值对组成的集合。其次,调用字典的get()获取相应的表达式。 from__future__importdivision x=1 y=2 operator="/" result={ "+" : x+y, "-" : x-y, "*" : x*y, "/" : x/y } print result.get(operator) 输出为0.5; 另一种使用switch分支语句的方案是创建一个switch类,处理程序的流程。 a) 创建一个switch类,该类继承自Python的祖先类object。调用构造函数init( )初始化需要匹配的字符串,并需要定义两个成员变量value和fall。Value用于存放需要匹配的字符串,fall用于记录是否匹配成功,初始值为false,标识匹配不成功。如果匹配成功,程序往后执行。 b) 定义一个match( )方法,该方法用于用于匹配case子句。这里需要考虑三种情况:首先是匹配成功的情况,其次是匹配失败的默认case子句,最后是case子句中没有使用break中断的情况。 c) 重写__iter__( )方法,定义该方法后才能使switch类用于循环语句中。__iter__( )调用match( )方法进行匹配。通过yield保留字,使函数可以在循环中迭代。此外,调用StopIteration异常中断循环。 d) 编写调用代码,在for…in…循环中使用switch类。 #!/usr/bin/python # -*- coding: UTF-8 -*- classswitch(object): def__init__(self, value): # 初始化需要匹配的值value self.value=value self.fall=False # 如果匹配到的case语句中没有break,则fall为true。 def__iter__(self): yieldself.match # 调用match方法 返回一个生成器 raiseStopIteration # StopIteration 异常来判断for循环是否结束 defmatch(self,*args): # 模拟case子句的方法 ifself.fallornotargs: # 如果fall为true,则继续执行下面的case子句 # 或case子句没有匹配项,则流转到默认分支。 returnTrue elifself.valueinargs: # 匹配成功 self.fall=True returnTrue else: # 匹配失败 returnFalse operator="+" x=1 y=2 forcaseinswitch(operator): # switch只能用于for in循环中 ifcase('+'): print x+y break ifcase('-'): printx-y break ifcase('*'): printx*y break ifcase('/'): printx/y break ifcase(): # 默认分支 print"" 2.while...语句 只要在一个条件为真的情况下,while语句允许你重复执行一块语句。while语句是所谓 循环 语句的一个例子。while语句有一个可选的else从句。 whileTrue: pass else: pass #else语句可选,当while为False时,else语句被执行。 pass是空语句。 3.for 循环 foriinrange(0, 5): print i else: pass # 打印0到4 注:当for循环结束后执行else语句;range(a, b)返回一个序列,从a开始到b为止,但不包括b,range默认步长为1,可以指定步长,range(0,10,2); 四、函数 函数通过def定义。def关键字后跟函数的标识符名称,然后跟一对圆括号,括号之内可以包含一些变量名,该行以冒号结尾;接下来是一块语句,即函数体。 defsumOf(a, b): returna+b 4.1 局部变量 在函数内定义的变量与函数外具有相同名称的其他变量没有任何关系,即变量名称对于函数来说是局部的。这称为变量的作用域。global语句, 为定义在函数外的变量赋值时使用global语句。 deffunc(): globalx print "x is ", x x=1 x=3 func() printx 以上代码,输出的结果为: 3 1 4.2 默认参数 通过使用默认参数可以使函数的一些参数是‘可选的’。 defsay(msg, times=1): print msg*times say("peter") say("peter", 3) 注意:只有在形参表末尾的那些参数可以有默认参数值,即不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参,只是因为赋给形参的值是根据位置而赋值的。 4.3 关键参数 如果某个函数有很多参数,而现在只想指定其中的部分,那么可以通过命名为这些参数赋值(称为‘关键参数’)。 优点:不必担心参数的顺序,使函数变的更加简单;假设其他参数都有默认值,可以只给我们想要的那些参数赋值。 deffunc(a, b=2, c=3): print"a is %s, b is %s, c is %s"%(a, b, c) func(1) #输出a is 1, b is 2, c is 3 func(1, 5) #输出a is 1, b is 5, c is 3 func(1, c=10) #输出a is 1, b is 2, c is 10 func(c=20, a=30) #输出a is 30, b is 2, c is 20 4.3 return语句 return语句用来从一个函数返回,即跳出函数。可从函数返回一个值。 没有返回值的return语句等价于return None。None表示没有任何东西的特殊类型。

资源下载

更多资源
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等操作系统。

用户登录
用户注册