一,前言

  • 进程:是程序,资源集合,进程控制块组成,是最小的资源单位
    • 特点:就对Python而言,可以实现真正的并行效果
    • 缺点:进程切换很容易消耗cpu资源,进程之间的通信相对线程来说比较麻烦  
  • 线程:是进程中最小的执行单位。
    • 特点无法利用多核,无法实现真正意义上是并行效果。
    • 优点:对于IO密集型的操作可以很好利用IO阻塞的时间

二,多进程

  2.1 multiprocessing模块介绍

  在上一节多线程中讲到,由于GIL的原因,多线程无法利用多核优势,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing。multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。multiprocessing模块的功能众多:支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。

  2.2 process类介绍

类的实例化(创建进程)
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,表示一个子进程中的任务(尚未启动) 强调:
1. 需要使用关键字的方式来指定参数
2. args指定的为传给target函数的位置参数,是一个元组形式,必须有逗号 参数介绍
group参数未使用,值始终为None target表示调用对象,即子进程要执行的任务 args表示调用对象的位置参数元组,args=(1,2,'hexin',) kwargs表示调用对象的字典,kwargs={'name':'hexin','age':18} name为子进程的名称 # process方法
p.start():启动进程,并调用该子进程中的p.run()
p.run():进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 p.terminate():强制终止进程p,不会进行任何清理操作,如果p创建了子进程,该子进程就成了僵尸进程,使用该方法需要特别小心这种情况。如果p还保存了一个锁那么也将不会被释放,进而导致死锁
p.is_alive():如果p仍然运行,返回True p.join([timeout]):主线程等待p终止(强调:是主线程处于等的状态,而p是处于运行的状态)。timeout是可选的超时时间,需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 # process 属性
p.daemon:默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置

p.name:进程的名称

p.pid:进程的pid

p.exitcode:进程在运行时为None、如果为–N,表示被信号N结束(了解即可)

p.authkey:进程的身份验证键,默认是由os.urandom()随机生成的32字符的字符串。这个键的用途是为涉及网络连接的底层进程间通信提供安全性,这类连接只有在具有相同的身份验证键时才能成功(了解即可)

  2.3 多进程创建

  创建形式一:普通形式

import time
import random
from multiprocessing import Process def fun(name):
print('%s begin' %name)
time.sleep(random.randrange(1, 3))
print('%s end' % name) if __name__ == '__main__':
p1 = Process(target=fun, args=('w',))
p2 = Process(target=fun,args=('a',))
p3 = Process(target=fun,args=('l',))
p4 = Process(target=fun,args=('l',)) p1.start()
p2.start()
p3.start()
p4.start()
print('主线程')

  输出结果:

主线程
w begin
a begin
l begin
l begin
a end
l end
w end
l end

  创建方式二:继承方式

import time
import random
from multiprocessing import Process class Sleep(Process):
def __init__(self,name):
super().__init__()
self.name = name def run(self):
print('%s sleep begin' % self.name)
time.sleep(random.randrange(1,5))
print('%s end' % self.name) if __name__ == '__main__':
for i in ['a', 'b', 'c']:
Sleep(i).start()
print("main")

  输出:

main
b sleep begin
a sleep begin
c sleep begin
c end
b end
a end

  2.4 进程同步

  进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的。

  共享同一打印终端,发现会有多行内容打印到一行的现象(多个进程共享并抢占同一个打印终端,乱了)

  既然可以用文件共享数据,那么进程间通信用文件作为数据传输介质就可以了啊,可以,但是有问题:1.效率 2.需要自己加锁处理

  加锁的目的是为了保证多个进程修改同一块数据时,同一时间只能有一个修改,即串行的修改,没错,速度是慢了,牺牲了速度而保证了数据安全。

  文件当做数据库,模拟抢票(Lock互斥锁)

#!/usr/bin/env python
# -*- coding:utf-8 -*- #文件db的内容为:{"count":2}
#注意一定要用双引号,不然json无法识别
from multiprocessing import Process,Lock
import json
import time
import random
import os def work(filename,lock): #买票
# lock.acquire()
with lock:
with open(filename,encoding='utf-8') as f:
dic=json.loads(f.read())
# print('剩余票数: %s' % dic['count'])
if dic['count'] > 0:
dic['count']-=1
time.sleep(random.randint(1,3)) #模拟网络延迟
with open(filename,'w',encoding='utf-8') as f:
f.write(json.dumps(dic))
print('%s 购票成功' %os.getpid())
else:
print('%s 购票失败' %os.getpid())
# lock.release() if __name__ == '__main__':
lock=Lock()
p_l=[]
for i in range(10):
p=Process(target=work,args=('db',lock))
p_l.append(p)
p.start()
for p in p_l:
p.join() print('主线程')

  输出:

购票成功
购票成功
购票失败
购票失败
购票失败
购票失败
购票失败
购票失败
购票失败
购票失败
主线程

三,进程间通信

  进程彼此之间互相隔离,要实现进程间通信(IPC),multiprocessing模块支持两种形式:队列和管道,这两种方式都是使用消息传递的。

  3.1 进程间通信(IPC)方式一:队列(推荐使用)

  队列方式一:Queue()

  队列先进先出,栈后进先出,创建队列的类(底层就是以管道和锁定的方式实现):

# 实例创建
Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。 # 参数说明
maxsize是队列中允许最大项数,省略则无大小限制。 # 属性介绍 q.put方法用以插入数据到队列中
put方法还有两个可选参数:blocked和timeout。
如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。
如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。 q.get方法可以从队列读取并且删除一个元素。
get方法有两个可选参数:blocked和timeout。
如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。
如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常. q.get_nowait():同q.get(False)
q.put_nowait():同q.put(False) q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目。
q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。
q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同q.empty()和q.full()一样

  实例:基于队列实现生产者和消费者模型

from multiprocessing import Process,Queue
import time,random,os def consumer(q):
while True:
time.sleep(random.randint(1,3))
res=q.get()
if res is None:break
print('\033[45m消费者拿到了:%s\033[0m' %res) def producer(seq,q):
for item in seq:
time.sleep(random.randint(1,3))
print('\033[46m生产者生产了:%s\033[0m' %item) q.put(item) if __name__ == '__main__':
q=Queue() c=Process(target=consumer,args=(q,))
c.start() producer(('包子%s' %i for i in range(5)),q)
q.put(None)
c.join()
print('主线程')

  输出:

生产者生产了:包子0
消费者拿到了:包子0
生产者生产了:包子1
消费者拿到了:包子1
生产者生产了:包子2
消费者拿到了:包子2
生产者生产了:包子3
消费者拿到了:包子3
生产者生产了:包子4
消费者拿到了:包子4
主线程

  队列方式二:JoinableQueue()

JoinableQueue([maxsize]):这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。

maxsize是队列中允许最大项数,省略则无大小限制。

JoinableQueue的实例p除了与Queue对象相同的方法之外还具有:

    q.task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发ValueError异常
q.join():生产者调用此方法进行阻塞,直到队列中所有的项目均被处理。阻塞将持续到队列中的每个项目均调用q.task_done()方法为止

  生产者消费者模型:

from multiprocessing import Process,JoinableQueue
import time,random
def consumer(q):
while True:
# time.sleep(random.randint(1,2))
res=q.get()
print('消费者拿到了 %s' %res)
q.task_done() def producer(seq,q):
for item in seq:
# time.sleep(random.randrange(1,2))
q.put(item)
print('生产者做好了 %s' %item)
q.join() if __name__ == '__main__':
q=JoinableQueue()
seq=('包子%s' %i for i in range(5)) p=Process(target=consumer,args=(q,))
p.daemon=True #设置为守护进程,在主线程停止时p也停止,但是不用担心,producer内调用q.join保证了consumer已经处理完队列中的所有元素
p.start() producer(seq,q) print('主线程')

  3.2 进程间通信(IPC)方式二:管道

  

# 创建实例
Pipe([duplex]):在进程之间创建一条管道,并返回元组(conn1,conn2),其中conn1,conn2表示管道两端的连接对象,强调一点:必须在产生Process对象之前产生管道 # 参数介绍
dumplex:默认管道是全双工的,如果将duplex射成False,conn1只能用于接收,conn2只能用于发送。 # 方法介绍
conn1.recv():接收conn2.send(obj)发送的对象。如果没有消息可接收,recv方法会一直阻塞。如果连接的另外一端已经关闭,那么recv方法会抛出EOFError。
conn1.send(obj):通过连接发送对象。obj是与序列化兼容的任意对象 conn1.close():关闭连接。如果conn1被垃圾回收,将自动调用此方法
conn1.fileno():返回连接使用的整数文件描述符
conn1.poll([timeout]):如果连接上的数据可用,返回True。timeout指定等待的最长时限。如果省略此参数,方法将立即返回结果。如果将timeout射成None,操作将无限期地等待数据到达。 conn1.recv_bytes([maxlength]):接收c.send_bytes()方法发送的一条完整的字节消息。maxlength指定要接收的最大字节数。如果进入的消息,超过了这个最大值,将引发IOError异常,
并且在连接上无法进行进一步读取。如果连接的另外一端已经关闭,再也不存在任何数据,将引发EOFError异常。
conn.send_bytes(buffer [, offset [, size]]):通过连接发送字节数据缓冲区,buffer是支持缓冲区接口的任意对象,offset是缓冲区中的字节偏移量,而size是要发送字节数。结果数据以单条消息的形式发出,然后调用c.recv_bytes()函数进行接收 conn1.recv_bytes_into(buffer [, offset]):接收一条完整的字节消息,并把它保存在buffer对象中,该对象支持可写入的缓冲区接口(即bytearray对象或类似的对象)。
offset指定缓冲区中放置消息处的字节位移。返回值是收到的字节数。如果消息长度大于可用的缓冲区空间,将引发BufferTooShort异常。

  生产者消费者实例:

from multiprocessing import Process,Pipe

import time,os
def consumer(p,name):
left,right=p
left.close()
while True:
try:
baozi=right.recv()
print('%s 收到包子:%s' %(name,baozi))
except EOFError:
right.close()
break
def producer(seq,p):
left,right=p
right.close()
for i in seq:
left.send(i)
# time.sleep(1)
else:
left.close()
if __name__ == '__main__':
left,right=Pipe() c1=Process(target=consumer,args=((left,right),'c1'))
c1.start() seq=(i for i in range(10))
producer(seq,(left,right)) right.close()
left.close() c1.join()
print('主进程')

  注意:生产者和消费者都没有使用管道的某个端点,就应该将其关闭,如在生产者中关闭管道的右端,在消费者中关闭管道的左端。如果忘记执行这些步骤,程序可能再消费者中的recv()操作上挂起。管道是由操作系统进行引用计数的,必须在所有进程中关闭管道后才能生产EOFError异常。因此在生产者中关闭管道不会有任何效果,付费消费者中也关闭了相同的管道端点。

  管道可以用于双向通信,利用通常在客户端/服务器中使用的请求/响应模型或远程过程调用,就可以使用管道编写与进程交互的程序,如下

from multiprocessing import Process,Pipe

import time,os
def adder(p,name):
server,client=p
client.close()
while True:
try:
x,y=server.recv()
except EOFError:
server.close()
break
res=x+y
server.send(res)
print('server done')
if __name__ == '__main__':
server,client=Pipe() c1=Process(target=adder,args=((server,client),'c1'))
c1.start() server.close() client.send((10,20))
print(client.recv())
client.close() c1.join()
print('主进程')

  输出:

30
server done
主进程

四,进程池

  4.1 进程池介绍

  开多进程的目的是为了并发,如果有多核,通常有几个核就开几个进程,进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行),但很明显需要并发执行的任务要远大于核数,这时我们就可以通过维护一个进程池来控制进程数目,比如httpd的进程模式,规定最小进程数和最大进程数。

  当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。而且对于远程过程调用的高级应用程序而言,应该使用进程池,Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,就重用进程池中的进程。在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。

  4.2 进程池使用

     4.2.1进程池方式一:

     同步调用:

from multiprocessing import Pool
import os,time def work(n):
print('{} run'.format(os.getpid()))
time.sleep(1)
return n ** 2 # ret if __name__ == '__main__':
p = Pool(3) # 创建3个进程
res_1 = []
for i in range(20):
res = p.apply(work,args=(i,))
'''同步调用,直到本次任务执行完毕拿到res,等待任务work执行的过程中可能有阻塞也可能没有阻塞,
但不管该任务是否存在阻塞,同步调用都会在原地等着,只是等的过程中若是任务发生了阻塞就会被夺走cpu的执行权限;
个人理解:程序判断两个子程序执行的间隔时间,过长则判断存在阻塞,届时夺走上次进程ID的使用权限,从进程池分配新的进程ID'''
res_1.append(res)
print(res_1)

    异步调用:

from multiprocessing import Pool
import os,time
def work(n):
print('%s run' %os.getpid())
time.sleep(3)
return n**2 if __name__ == '__main__':
p=Pool(3) #进程池中从无到有创建三个进程,以后一直是这三个进程在执行任务
res_l=[]
for i in range(10):
print(i) # for循环会提前运行完毕,进程池内的任务还未执行。
res=p.apply_async(work,args=(i,)) #同步运行,阻塞、直到本次任务执行完毕拿到res
res_l.append(res) #将调用apply_async方法,得到返回进程内存地址结果 #异步apply_async用法:如果使用异步提交的任务,主进程需要使用join,等待进程池内任务都处理完,然后可以用get收集结果,
# 否则,主进程结束,进程池可能还没来得及执行,也就跟着一起结束了
p.close()
p.join()
for res in res_l:
print(res.get()) #使用get来获取apply_aync的结果,如果是apply,则没有get方法,因为apply是同步执行,立刻获取结果,也根本无需get

    apply_sync和apply方法

# apply_async方法
from multiprocessing import Process,Pool
import time def func(msg):
print( "msg:", msg)
time.sleep(1)
return msg if __name__ == "__main__":
pool = Pool(processes = 3)
res_l=[]
for i in range(10):
print(i)
msg = "hello %d" %(i)
res=pool.apply_async(func, (msg, )) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
res_l.append(res) # 将apply_async方法得到的内存地址结果加入列表
print("==============================>") #没有后面的join,或get,则程序整体结束,进程池中的任务还没来得及全部执行完
# 也都跟着主进程一起结束了 pool.close() #关闭进程池,防止进一步操作。如果所有操作持续挂起,它们将在工作进程终止前完成
pool.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 print(res_l) #看到的是<multiprocessing.pool.ApplyResult object at 0x10357c4e0>对象组成的列表,而非最终的结果,但这一步
# 是在join后执行的,证明结果已经计算完毕,剩下的事情就是调用每个对象下的get方法去获取结果
for i in res_l:
print(i.get()) #使用get来获取apply_aync的结果,如果是apply,则没有get方法,因为apply是同步执行,立刻获取结果,也根本无需get #apply方法
from multiprocessing import Process,Pool
import time def func(msg):
print( "msg:", msg)
time.sleep(0.1)
return msg if __name__ == "__main__":
pool = Pool(processes = 3)
res_l=[]
for i in range(10):
msg = "hello %d" %(i)
res=pool.apply(func, (msg, )) #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
res_l.append(res) #同步执行,即执行完一个拿到结果,再去执行另外一个
print("==============================>")
pool.close()
pool.join() #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束 print(res_l) #看到的就是最终的结果组成的列表
for i in res_l: #apply是同步的,所以直接得到结果,没有get()方法
print(i)

    map方法

#map
import os,time
from multiprocessing import Pool def func(i):
time.sleep(1)
print('子进程{}'.format(os.getpid()))
return i if __name__ == '__main__':
p = Pool(5)
ret = p.map(func,range(10)) # func(next(range(10)))
print(ret)

   4.2.1 concurrent.futures 模块实现‘池’

    同步调用:

# #同步调用:提交/调用一个任务,然后就在原地等着,等到该任务执行完毕拿到结果,再执行下一行代码
from concurrent.futures import ProcessPoolExecutor
import time def save_test(name,n):
n = n+1
time.sleep(n)
print("{}的名字次数为{}".format(name,n))
return n if __name__ == '__main__':
start = time.time()
ex = ProcessPoolExecutor(max_workers=3)
lista = ["Tom","Jerry","XiaoHua","Ming"] for i,j in enumerate(lista):
#存在两个以上的参数时,直接用逗号隔开,不需要用括号
task = ex.submit(save_test,j,i).result()
print(task)
#ex.shutdown(wait=True)是进程池内部的进程都执行完毕,才会关闭,然后执行后续代码
ex.shutdown(wait=True)
print("主进程直接运行")
stop = time.time()
print(stop-start)

    异步调用:

#异步调用: 提交/调用一个任务,不在原地等着,直接执行下一行代码
from concurrent.futures import ProcessPoolExecutor
import time def save_test(name,n):
n = n+1
time.sleep(n)
print("{}的名字次数为{}".format(name,n))
return n if __name__ == '__main__':
obj = list()
start = time.time()
ex = ProcessPoolExecutor(max_workers=3)
lista = ["letme","Mlxg","XiaoHu","Ming"] for i,j in enumerate(lista):
#存在两个以上的参数时,直接用逗号隔开,不需要用括号
task = ex.submit(save_test,j,i)
obj.append(task)
#ex.shutdown(wait=True)是进程池内部的进程都执行完毕,才会关闭,然后执行后续代码
ex.shutdown(wait=True)
print("主进程直接运行")
for i in obj:
print(i.result())
stop = time.time()
print(stop-start)

    map方法使用

from concurrent.futures import ProcessPoolExecutor

import urllib.request
URLS = ['http://www.163.com', 'https://www.baidu.com/', 'https://github.com/'] def load_url(url):
with urllib.request.urlopen(url, timeout=60) as conn:
print('%r page is %d bytes' % (url, len(conn.read()))) if __name__ == '__main__':
executor = ProcessPoolExecutor(max_workers=3)
executor.map(load_url,URLS)
print('主进程')

五,总结

  用futures的写法上更简洁一些,concurrent.futures的性能并没有更好,只是让编码变得更简单。考虑并发编程的时候,任何简化都是好事。从长远来看,concurrent.futures编写的代码更容易维护。
  使用map时,future是逐个迭代提交,multiprocessing.Pool是批量提交jobs,因此对于大批量jobs的处理,multiprocessing.Pool效率会更高一些。对于需要长时间运行的作业,用future更佳,future提供了更多的功能(callback, check status, cancel)。
  concurrent.futures.ProcessPoolExecutor是对multiprocessing的封装,在运行时需导入__main__,不能直接在交互窗口工作。

Python 多进程和进程池的更多相关文章

  1. python多进程,以及进程池并发

    模拟多进程 #!/usr/bin/env python#-*- coding:utf-8 -*-import timefrom multiprocessing import Process def s ...

  2. python多进程,进程池,数据共享,进程通信,分布式进程

    一.操作系统中相关进程的知识   Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊.普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前 ...

  3. python 多进程——使用进程池,多进程消费的数据)是一个队列的时候,他会自动去队列里依次取数据

    我的mac 4核,因此每次执行的时候同时开启4个线程处理: # coding: utf-8 import time from multiprocessing import Pool def long_ ...

  4. python中的进程池

    1.进程池的概念 python中,进程池内部会维护一个进程序列.当需要时,程序会去进程池中获取一个进程. 如果进程池序列中没有可供使用的进程,那么程序就会等待,直到进程池中有可用进程为止. 2.进程池 ...

  5. python中的进程池:multiprocessing.Pool()

    python中的进程池: 我们可以写出自己希望进程帮助我们完成的任务,然后把任务批量交给进程池 进程池帮助我们创建进程完成任务,不需要我们管理.进程池:利用multiprocessing 下的Pool ...

  6. Python中的进程池与线程池(包含代码)

    Python中的进程池与线程池 引入进程池与线程池 使用ProcessPoolExecutor进程池,使用ThreadPoolExecutor 使用shutdown 使用submit同步调用 使用su ...

  7. python学习笔记——multiprocessing 多进程组件 进程池Pool

    1 进程池Pool基本概述 在使用Python进行系统管理时,特别是同时操作多个文件目录或者远程控制多台主机,并行操作可以节约大量时间,如果操作的对象数目不大时,还可以直接适用Process类动态生成 ...

  8. Python 3 并发编程多进程之进程池与回调函数

    Python 3 进程池与回调函数 一.进程池 在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间.多进程是实现并发的手段之一,需要注意 ...

  9. Python并发编程-进程池及异步方式

    进程池的基本概念 为什么有进程池的概念 效率问题 每次开启进程,都需要开启属于这个进程的内存空间 寄存器,堆栈 进程过多,操作系统的调度 进程池 python中的 先创建一个属于进程的池子 这个池子指 ...

随机推荐

  1. python第10天(下)

    https://www.cnblogs.com/zingp/p/6863170.html  一:IO模型介绍 IO发生时涉及的对象和步骤 对于一个网络IO(network IO),它会涉及到两个系统对 ...

  2. Spring AOP概念理解

    1.我所知道的aop 初看aop,上来就是一大堆术语,而且还有个拉风的名字,面向切面编程,都说是OOP的一种有益补充等等.一下子让你不知所措,心想着:怪不得很多人都和我说aop多难多难.当我看进去以后 ...

  3. Concept of function continuity in topology

    Understanding of continuity definition in topology When we learn calculus in university as freshmen, ...

  4. Redis数据结构之skiplist

    本文及后续文章,Redis版本均是v3.2.8 我们会经常选择使用sorted set数据结构,是由于其提供的操作非常丰富,可以满足非常多的应用场景.sorted set数据结构是由skiplist( ...

  5. Java_打印从一个数到另一个数之间的整数,并每5个为一行

    import java.util.Scanner; public class Dayin_100 { public static void main(String[] args) { System.o ...

  6. Imcash平台测评报告

    ImCash是由全球知名量子基金(QuantumFund)与美国好事达保险公司 (ALL ) 联合投资美国区块链金融资本(BFC)打造全球首款量子基金数字资产服务平台 . ImCash作为全球首款量子 ...

  7. JDK配置环境变量不成功的原因

    根据自己配置环境变量遇到的问题进行总结: 1.二次安装需要注意的问题 由于已经安装了一次的原因,此时的注册表已经有了安装记录. 建议删除jdk的记录 首先打开注册表 开始菜单→运行.或者直接键盘按下W ...

  8. python面试必问 知识整理

      一 数据类型 1 数字 整型与浮点型   #整型int 作用:年纪,等级,身份证号,qq号等整型数字相关 定义: age=10 #本质age=int(10) #浮点型float 作用:薪资,身高, ...

  9. CentOS下 SVN版本控制的安装(包括yum与非yum)的步骤记录。

    一.yum安装 rpm -qa subversion //检查是否安装了低版本的SVN yum remove subversion //如果存储旧版本,卸载旧版本SVN 开始安装 yum -y ins ...

  10. with(window) onload=onresize=function(){} 写法

    with(window) onload=onresize=function(){} 写法 with的用法: with(对象A) { 语句块 } 语句块中可以直接使用 对象A中的属性和方法 ------ ...