进程:最小的数据单元

线程:最小的执行单元

一:

1:线程1

  1. import threading #线程
  2. import time
  3. def Music():
  4. print("Listen Music Begin %s" %time.ctime())
  5. time.sleep()
  6. print("Listen Music End %s" %time.ctime())
  7. def Game():
  8. print("Play Game Begin %s" %time.ctime())
  9. time.sleep()
  10. print("Play Game End %s" %time.ctime())
  11. if __name__ == '__main__':
  12. t1 = threading.Thread(target=Music)
  13. t1.start()
  14. t2 = threading.Thread(target=Game)
  15. t2.start()
  16.  
  17. print("ending......")

实例1

  1. import threading #线程
  2. import time
  3. def Music():
  4. print("Listen Music Begin %s" %time.ctime())
  5. time.sleep(3)
  6. print("Listen Music End %s" %time.ctime())
  7. def Game():
  8. print("Play Game Begin %s" %time.ctime())
  9. time.sleep(5)
  10. print("Play Game End %s" %time.ctime())
  11. if __name__ == '__main__':
  12. t1 = threading.Thread(target=Music)
  13. t1.start()
  14. t2 = threading.Thread(target=Game)
  15. t2.start()
  16. t1.join()
  17. t2.join()
  18. print("ending......")

线程join

  1. import threading #线程
  2. import time
  3. def Music(musicName):
  4. print("Listen Music【%s】 Begin %s" %(musicName,time.ctime()))
  5. time.sleep(3)
  6. print("Listen Music【%s】 End %s" %(musicName,time.ctime()))
  7. def Game(playName):
  8. print("Play Game【%s】 Begin %s" %(playName,time.ctime()))
  9. time.sleep(5)
  10. print("Play Game【%s】 End %s" %(playName,time.ctime()))
  11. if __name__ == '__main__':
  12. t1 = threading.Thread(target=Music,args=("My Heart Will Go On",))
  13. t2 = threading.Thread(target=Game,args=("植物大战僵尸",))
  14. threads=[]
  15. threads.append(t1)
  16. threads.append(t2)
  17. for t in threads:
  18. t.start();
  19. print("ending......")

线程参数

  1. import threading #线程
  2. import time
  3. def Music(musicName):
  4. print("Listen Music【%s】 Begin %s" %(musicName,time.ctime()))
  5. time.sleep(3)
  6. print("Listen Music【%s】 End %s" %(musicName,time.ctime()))
  7. def Game(playName):
  8. print("Play Game【%s】 Begin %s" %(playName,time.ctime()))
  9. time.sleep(5)
  10. print("Play Game【%s】 End %s" %(playName,time.ctime()))
  11. t1 = threading.Thread(target=Music,args=("My Heart Will Go On",))
  12. t2 = threading.Thread(target=Game,args=("植物大战僵尸",))
  13. threads=[]
  14. threads.append(t1)
  15. threads.append(t2)
  16. if __name__ == '__main__':
  17. t2.setDaemon(True)
  18. for t in threads:
  19. t.start();
  20. print("ending......")

守护线程

  1. # 多线程为什么要使用锁?
  2. # 多线程共用一个数据集,不使用可能会造成数据不准确
  3. #1:引入多线程模块
  4. import threading
  5. import time
  6. # 2:定义一个变量(数据集)
  7. num=100
  8. # 3:定义一个方法,操作全局变量
  9. def sub():
  10. global num
  11. temp = num
  12. time.sleep(0.001)
  13. num=temp-1
  14. # 4:创建多个线程
  15. ts=[]
  16. for i in range(0,100):
  17. t=threading.Thread(target=sub)
  18. t.start()
  19. ts.append(t)
  20. for t in ts:
  21. t.join()
  22. print(num)

未加锁,数据结果有误

  1. # 多线程为什么要使用锁?
  2. # 多线程共用一个数据集,不使用可能会造成数据不准确
  3. #1:引入多线程模块
  4. import threading
  5. import time
  6. # 2:定义一个变量(数据集)
  7. num=100
  8. # 3:定义一个方法,操作全局变量
  9. # 5:创建锁
  10. lock=threading.Lock()
  11. def sub():
  12. global num
  13. # 5.1 加锁
  14. lock.acquire()
  15. temp = num
  16. time.sleep(0.001)
  17. num=temp-1
  18. # 5.2 释放锁
  19. lock.release()
  20. # 4:创建多个线程
  21. ts=[]
  22. for i in range(0,100):
  23. t=threading.Thread(target=sub)
  24. t.start()
  25. ts.append(t)
  26. for t in ts:
  27. t.join()
  28.  
  29. print(num)

同步锁

  1. #当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁
  2. #线程的另一种实现方式(通过自定义类)
  3. #1:引入threading、time
  4. import threading
  5. import time
  6. # 定义两个锁
  7. lockA=threading.Lock()
  8. lockB=threading.Lock()
  9. #3:定义一个线程(线程中存在两个方法,存在递归调用)
  10. class MyThread(threading.Thread):
  11. #定义两个方法
  12. def actionA(self):
  13. # 获取A锁
  14. lockA.acquire()
  15. print(self.name,"gotA",time.ctime())
  16. time.sleep(1)
  17. #然后再获取B锁
  18. lockB.acquire()
  19. print(self.name,"gotB",time.ctime())
  20. time.sleep(2)
  21. # 先释放B锁,
  22. lockB.release()
  23. # 后释放A锁
  24. lockA.release()
  25. def actionB(self):
  26. # 获取B锁
  27. lockB.acquire()
  28. print(self.name, "gotB", time.ctime())
  29. time.sleep(1)
  30. # 然后再获取A锁
  31. lockA.acquire()
  32. print(self.name, "gotA", time.ctime())
  33. time.sleep(2)
  34. # 先释放A锁,
  35. lockA.release()
  36. # 后释放B锁
  37. lockB.release()
  38. #实现run方法
  39. def run(self):
  40. self.actionA()
  41. self.actionB()
  42.  
  43. # 4:创建多个线程
  44. for i in range(0,5):
  45. t=MyThread()
  46. t.start()

死锁现象

  1. #当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁
  2. #线程的另一种实现方式(通过自定义类)
  3. #1:引入threading、time
  4. import threading
  5. import time
  6. # 定义两个锁
  7. lockA=threading.Lock()
  8. lockB=threading.Lock()
  9.  
  10. lockR=threading.RLock() #把两个锁替换成一个RLock,内部通过计数器实现
  11. #3:定义一个线程(线程中存在两个方法,存在递归调用)
  12. class MyThread(threading.Thread):
  13. #定义两个方法
  14. def actionA(self):
  15. # 获取A锁
  16. # lockA.acquire()
  17. lockR.acquire()
  18. print(self.name,"gotA",time.ctime())
  19. time.sleep(1)
  20. #然后再获取B锁
  21. # lockB.acquire()
  22. lockR.acquire()
  23. print(self.name,"gotB",time.ctime())
  24. time.sleep(2)
  25. # 先释放B锁,
  26. # lockB.release()
  27. lockR.release()
  28. # 后释放A锁
  29. # lockA.release()
  30. lockR.release()
  31. def actionB(self):
  32. # 获取B锁
  33. # lockB.acquire()
  34. lockR.acquire()
  35. print(self.name, "gotB", time.ctime())
  36. time.sleep(1)
  37. # 然后再获取A锁
  38. # lockA.acquire()
  39. lockR.acquire()
  40. print(self.name, "gotA", time.ctime())
  41. time.sleep(2)
  42. # 先释放A锁,
  43. # lockA.release()
  44. lockR.release()
  45. # 后释放B锁
  46. lockR.release()
  47. # lockB.release()
  48. #实现run方法
  49. def run(self):
  50. self.actionA()
  51. self.actionB()
  52.  
  53. # 4:创建多个线程
  54. for i in range(0,5):
  55. t=MyThread()
  56. t.start()

递归锁,解决死锁

  1. # 1:引入包
  2. import threading
  3. import time
  4. # 2:创建同步锁
  5. event = threading.Event()
  6. #3:创建线程对象
  7. class Boss(threading.Thread):
  8. def run(self):
  9. print("大家加班")
  10. event.set()
  11. time.sleep(5)
  12. print("下班了")
  13. event.set()
  14. class Worker(threading.Thread):
  15. def run(self):
  16. event.wait()
  17. print("不加班,不加班")
  18. time.sleep(1)
  19. event.clear()
  20. event.wait()
  21. print("Oh Yeah")
  22. # 4:创建线程对象,并放入到线程集合中
  23. ts=[]
  24. t=Boss()
  25. ts.append(t)
  26. for i in range(0,5):
  27. ts.append(Worker())
  28. for t in ts:
  29. t.start()

同步锁

  1. # 信号量类似于停车场,一次只能处理n个线程
  2. # 1:导包
  3. import threading,time
  4. # 2:设置信号量
  5. semaphore = threading.Semaphore(5)
  6. # 3:创建线程对象
  7. class MyThread(threading.Thread):
  8. def run(self):
  9. if semaphore.acquire():
  10. print(self.name)
  11. time.sleep(3)
  12. semaphore.release()
  13.  
  14. # 4:创建线程对象
  15. for i in range(0,20):
  16. t=MyThread()
  17. t.start()

信号量

  1. # 队列:多线程,线程安全
  2. # 1:引包
  3. import queue,time
  4. # 2:创建对象
  5. q=queue.Queue(3) #3表示队列的总容量为3、默认为先进先出类型
  6. # 3:常用的方法
  7. q.put("#3333") #添加数据
  8. q.put({"ab":"cd"})
  9.  
  10. print(q.get()) #获取数据
  11. print(q.qsize()) #获取队列的长度
  12. print(q.empty()) #判断是否为空
  13. print(q.full()) #判断是否已满
  14. print(q.task_done()) #每对队列进行一次操作以后就会返回True
  15. print(q.join()) #task_done 对应的就是join

队列的常见属性

  1. # 通过队列,设置一个生产者消费者的开发模型
  2. # 1:引包
  3. import threading,queue,time,random
  4. # 2:定义队列
  5. que=queue.Queue()
  6. # 3:定义两个生产者、消费者的类
  7. def Producer(name):
  8. countBaoZi=1;
  9. while countBaoZi <= 10:
  10. # print("包子数量小于10,开始生产包子")
  11. time.sleep(random.randrange(1,3))
  12. que.put(countBaoZi)
  13. print("生产者:%s,生产了【包子%s】" % (name, countBaoZi))
  14. countBaoZi = countBaoZi + 1
  15. def Consumer(name):
  16. countBaoZi=1
  17. while countBaoZi<=10:
  18. time.sleep(random.randrange(1,4))
  19. if que.empty():
  20. print("老板没包子了")
  21. else:
  22. print("现在还有%s个包子" % que.qsize())
  23. curBaoZi = que.get()
  24. print("消费者:%s,吃了包子【%s】" % (name, curBaoZi))
  25.  
  26. # 4:创建多个线程
  27. producerA = threading.Thread(target=Producer,args=("A大厨",))
  28. consumerA = threading.Thread(target=Consumer,args=("A君",))
  29. consumerB = threading.Thread(target=Consumer,args=("B君",))
  30.  
  31. producerA.start()
  32. consumerA.start()
  33. consumerB.start()

队列-线程 生产者、消费者模式

  1. # 通过队列,设置一个生产者消费者的开发模型
  2. # 升级版,包子吃了以后,还需要再去检查一下,有没有包子if que.empty() 这样浪费时间,
  3. # 应该是:吃完就告诉老板直接生产,生产好了再通知客户去吃
  4. # 1:引包
  5. import threading,queue,time,random
  6. # 2:定义队列
  7. que=queue.Queue()
  8. # 3:定义两个生产者、消费者的类
  9. def Producer(name):
  10. countBaoZi=1;
  11. while countBaoZi <= 10:
  12. time.sleep(random.randrange(1,3))
  13. que.put(countBaoZi)
  14. print("生产者:%s,生产了【包子%s】" % (name, countBaoZi))
  15. countBaoZi = countBaoZi + 1
  16. que.join()
  17.  
  18. def Consumer(name):
  19. countBaoZi=1
  20. while countBaoZi<=10:
  21. time.sleep(random.randrange(1,4))
  22. print("现在还有%s个包子" % que.qsize())
  23. curBaoZi = que.get()
  24. time.sleep(1)
  25. print("消费者:%s,吃了包子【%s】" % (name, curBaoZi))
  26. que.task_done()
  27.  
  28. # 4:创建多个线程
  29. producerA = threading.Thread(target=Producer,args=("A大厨",))
  30. consumerA = threading.Thread(target=Consumer,args=("A君",))
  31. consumerB = threading.Thread(target=Consumer,args=("B君",))
  32.  
  33. producerA.start()
  34. consumerA.start()
  35. consumerB.start()

队列-线程 生产消费2

二 进程

  1. # 1:导包
  2. import time
  3. from multiprocessing import Process
  4. # 2:创建进程对象集合
  5. pros=[]
  6. # 3:定义方法
  7. def music(musicName):
  8. print("开始播放:%s.%s" %(musicName,time.ctime()))
  9. time.sleep(2)
  10. print("播放结束:%s.%s" %(musicName,time.ctime()))
  11. def play(gameName):
  12. print("开始打:%s.%s" %(gameName,time.ctime()))
  13. time.sleep(5)
  14. print("游戏结束:%s.%s" %(gameName,time.ctime()))
  15. if __name__ == '__main__':
  16. # 4:创建进行对象
  17. mu=Process(target=music,args=("My Heart Will Go On",))
  18. mu.start()
  19. mg=Process(target=play,args=("植物大战僵尸",))
  20. mg.start()

进程

  1. # 1:导包
  2. import time
  3. from multiprocessing import Process
  4. # 2:创建进程对象集合
  5. pros=[]
  6. # 3:定义方法
  7. def music(musicName):
  8. print("开始播放:%s.%s" %(musicName,time.ctime()))
  9. time.sleep(2)
  10. print("播放结束:%s.%s" %(musicName,time.ctime()))
  11. def play(gameName):
  12. print("开始打:%s.%s" %(gameName,time.ctime()))
  13. time.sleep(5)
  14. print("游戏结束:%s.%s" %(gameName,time.ctime()))
  15. if __name__ == '__main__':
  16. # 4:创建进行对象
  17. mu=Process(target=music,args=("My Heart Will Go On",))
  18. # 4.2:进程常用的属性和方法
  19. #mu.join() #进程阻塞
  20. mu.start() #开启进程
  21. time.sleep(1)
  22. mu.terminate() #结束进程
  23. print(" 进程名称 %s, 进程编码 %s,"%(mu.name,mu.pid))

常用的属性和方法

进程之间的三种通讯方法

进程队列

  1. # 1:导包
  2. from multiprocessing import Process,Queue
  3. import time
  4. #2:定义一个方法,用于向队列中赋值
  5. def putAction(q,n):
  6. q.put(n*(n+1))
  7. print("当前队列的id:",id(q))
  8.  
  9. if __name__ == '__main__':
  10. # 3:创建一个队列
  11. que=Queue()
  12. print("main方法中队列的id:", id(que))
  13. # 4:通过循环创建多个进程
  14. for i in range(0,3):
  15. p=Process(target=putAction,args=(que,i,))
  16. p.start()
  17. print(que.get())
  18. print(que.get())
  19. print(que.get())

通过进程队列实现数据通信

  1. # 管道相当于生成两个连接对象,一个主进程使用,另外一个传递给子进程使用
  2. # 1:导包
  3. from multiprocessing import Process,Pipe
  4. import time
  5. # 2:定义函数
  6. def ConnAction(conn):
  7. # 获取传递过来的conn连接对象
  8. print("准备发送消息,时间%s"%(time.ctime()))
  9. conn.send("土豆土豆,我是地瓜,收到请回答")
  10. time.sleep(2)
  11. print("准备接收消息,时间%s"%(time.ctime()))
  12. responInfo = conn.recv()
  13. print(responInfo,time.ctime())
  14.  
  15. if __name__ == '__main__':
  16. # 创建管道对象
  17. par_conn,child_conn=Pipe()
  18. # 创建进程
  19. p=Process(target=ConnAction,args=(child_conn,))
  20. p.start()
  21. print("主进程,准备接收消息,%s"%(time.ctime()))
  22. respons=par_conn.recv()
  23. print(respons,time.ctime())
  24. time.sleep(2)
  25. print("主进程,准备发送消息,%s"%(time.ctime()))
  26. par_conn.send("地瓜地瓜,我是土豆");

通过管道实现数据通信

  1. # 1:导包
  2. from multiprocessing import Process,Manager
  3. #2:定义方法
  4. def manaAction(d,l,n):
  5. # 对字典进行操作
  6. d[n]=""
  7. d[""]=2
  8. # 对列表进行操作
  9. l.append(n)
  10. if __name__ == '__main__':
  11. # 创建Manager对象中的数据类型
  12. with Manager() as manager:
  13. d=manager.dict()
  14. l=manager.list(range(5))
  15. p_list=[]
  16. # 创建进程
  17. for i in range(0,5):
  18. p=Process(target=manaAction,args=(d,l,i))
  19. p.start()
  20. p_list.append(p)
  21. for res in p_list:
  22. res.join()
  23. print(d)
  24. print(l)

通过Manager实现数据通信

  1. # 1:导入包
  2. from multiprocessing import Process,Lock
  3. import time
  4. #定义方法
  5. def printPro(l,n):
  6. with l:
  7. print("Hello,World %s,%s"%(n,time.ctime()))
  8. time.sleep(1)
  9.  
  10. if __name__ == '__main__':
  11. l=Lock()
  12. for i in range(0, 5):
  13. p = Process(target=printPro, args=(l,i,))
  14. p.start()

进程锁

  1. # 1:导包
  2. from multiprocessing import Process,Pool
  3. import time
  4.  
  5. # 3:创建方法
  6. def foo(i):
  7. time.sleep(1)
  8. print(i)
  9. return i
  10. # 4:创建回调方法
  11. def bar(arg):
  12. #回调方法在主函数中执行
  13. print("hello,%s"%arg)
  14.  
  15. if __name__ == '__main__':
  16. # 2:创建进程池对象
  17. pool = Pool(5)
  18. for i in range(0,30):
  19. pool.apply_async(func=foo,args=(i,),callback=bar)
  20. pool.close()
  21. pool.join()

进程池

三 协程

  协程是一种非抢占式程序,其本质是一个线程。

  优点:1:灭有切换消耗;2:没有锁的概念

  缺点:无法使用多核,但是可以通过多进程+协程弥补

  1. # 通过yield来实现
  2. # 1:导包
  3. import time
  4. #2:消费者
  5. def Consumer(name):
  6. print("准备开始吃包子")
  7. while True:
  8. newbaozi=yield
  9. print("%s吃了包子%s"%(name,newbaozi))
  10. #3:生产者
  11. def Product():
  12. r=con.__next__()
  13. r2=con2.__next__()
  14. baoziName=1
  15. while True:
  16. time.sleep(1)
  17. print("生产者,生产了%s和%s包子"%(baoziName,baoziName+1))
  18. con.send(baoziName)
  19. con2.send(baoziName+1)
  20. baoziName+=2
  21. #主方法
  22. if __name__ == '__main__':
  23. #创建两个用户
  24. con=Consumer("张三")
  25. con2=Consumer("李四")
  26. Product()

协程-yield

  1. from greenlet import greenlet
  2. def test1():
  3. print(12)
  4. gr2.switch()
  5. print(34)
  6. gr2.switch()
  7. def test2():
  8. print(56)
  9. gr1.switch()
  10. print(78)
  11. gr1 = greenlet(test1)
  12. gr2 = greenlet(test2)
  13. gr1.switch()

协程-greenlet

  1. # 1:导包
  2. import gevent
  3. import requests,time
  4.  
  5. # 记录开始时间
  6. start = time.time()
  7. def f(url):
  8. # print("Get:%s" %url)
  9. reap=requests.get(url)
  10. data=reap.text
  11. print("%s网址上一共有%s字节"%(url,len(data)))
  12. gevent.joinall([
  13. gevent.spawn(f, 'https://www.python.org/'),
  14. gevent.spawn(f, 'https://www.yahoo.com/'),
  15. gevent.spawn(f, 'https://www.baidu.com/'),
  16. gevent.spawn(f, 'https://www.sina.com.cn/'),
  17. ])
  18. print("耗时",time.time()-start)
  19. f('https://www.python.org/')
  20. f('https://www.yahoo.com/')
  21. f('https://www.baidu.com/')
  22. f('https://www.sina.com.cn/')
  23. print("耗时",time.time()-start)

协程-gevent

饮冰三年-人工智能-Python-20 Python线程、进程、线程的更多相关文章

  1. 饮冰三年-人工智能-Python-22 Python初识Django

    1:一个简单的web框架 # 导包 from wsgiref.simple_server import make_server #自定义个处理函数 def application(environ,st ...

  2. 饮冰三年-人工智能-Python-21 Python数据库MySql

    一:下载与安装 1:下载地址:https://dev.mysql.com/downloads/mysql/ 2:安装MySql 打开下载文件解压到指定文件目录.(我这里解压目录为D:\MySql\my ...

  3. 饮冰三年-人工智能-Python-19 Python网络编程

    Socket:套接字.作用:我们只需要安照socket的规定去编程,就不需要深入理解tcp/udp协议也可以实现 1:TCP协议 1.1  客户端服务端循环收发消息 # 1:引入stock模块(导包) ...

  4. 饮冰三年-人工智能-Python-10之C#与Python的对比

    1:注释 C# 中 单行注释:// 多行注释:/**/ python 中 单行注释:# 多行注释:“““内容””” 2:字符串 C#中 "" 用双引号如("我是字符串&q ...

  5. 饮冰三年-人工智能-linux-08 软件包管理(Python的安装)

    1:软件包存放的位置 media/CentOS_6.9_Final/Packages文件夹下 2.RPM就是Red Hat Package Manger(红帽软件包管理工具)的缩写. 2.1 常用的命 ...

  6. 饮冰三年-人工智能-Python-30 python开发中常见的错误

    1:触发条件:创建的实体类生成到数据库表时报错 报错信息:TypeError: __init__() missing 1 required positional argument: 'on_delet ...

  7. 饮冰三年-人工智能-Python-23 Python PyCharm 使用中常见的问题

    一:软件工具使用中遇到的问题 1:AttributeError: module 'pip' has no attribute 'main'问题 处理方法: a:找到JetBrains\PyCharm ...

  8. 饮冰三年-人工智能-Python-18Python面向对象

    1 类与实例对方法和属性的修改 class Chinese: # 这是一个Chinese的类 #定义一个类属性,又称为静态数据或者静态变量,相当于C#中的static country="Ch ...

  9. 饮冰三年-人工智能-Python-25 Django admin

    简介:一个关于后台数据库管理的工具 1:创建一个新的项目 2:设置models,并通过命令生成数据库表 from django.db import models class Book(models.M ...

随机推荐

  1. 2.6 datetime 模块

    目录 2.6.1  常用类 2.6.1.1 datetime.date 2.6.1.2 datetime.time 2.6.1.3 datetime.datetime 2.6.1.4 datetime ...

  2. beego框架的最简单登入演示

    一.controllers逻辑代码 func (c *UserController) Get() { c.TplName="login.html" } func (c *UserC ...

  3. [JDK8]读写锁的改进:StampedLock

    StampedLock是Java8引入的一种新的锁机制,简单的理解,可以认为它是读写锁的一个改进版本,读写锁虽然分离了读和写的功能,使得读与读之间可以完全并发,但是读和写之间依然是冲突的,读锁会完全阻 ...

  4. 基于alpine制作php镜像

    alpine包搜索https://pkgs.alpinelinux.org/ 安装依赖库 apk add --no-cache xxx 可以基于php apline镜像自行增加或删除扩展. https ...

  5. 第九节: 利用RemoteScheduler实现Sheduler的远程控制

    一. RemoteScheduler远程控制 1. 背景: 在A服务器上部署了一个Scheduler,我们想在B服务器上控制这个Scheduler. 2. 猜想: A服务器上的Scheduler需要有 ...

  6. css选择器(常规选择器,伪类选择器,伪元素选择器,根元素选择器)

    前言 CSS的一个核心特性是能向文档中的一组元素类型应用某些规则,本文将详细介绍CSS选择器 选择器 [通配选择器] 星号*代表通配选择器,可以与任何元素匹配 *{color: red;} [元素选择 ...

  7. python中的GIL详解

    GIL是什么 首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念.就好比C++是一套语言(语法)标准,但是可以用不同的编译器来编译成可 ...

  8. 用 Mathematica 获取图片的 RGB 三基色

    ColorConvert[*, "RGB"] // InputForm 其中 * 表示你把你的图片拖入 Mathematica 中.

  9. Java8从对象列表中取出某个属性的列表

    List<属性值类型> 属性List = 对象List.stream().map(对象::get方法()).collect(Collectors.toList()); 例如: List&l ...

  10. 在Windows上安装Arduino-IDE

    Arduino IDE的官方下载地址为:http://arduino.cc/en/Main/Software 也可以从我的网盘下载:win系统 1.8.9版本 链接:https://pan.baidu ...