進程(并發,并行) join start 進程池 (同步異步)

一、背景知識

  顧名思義,進程即正在執行的一個過程。進程是對正在運行程序的一個抽象。進程的概念起源于操作系統,是操作系統最核心的概念,也是操作系統提供的最古老也是最重要的抽象概念之一。操作系統的其他所有內容都是圍繞進程的概念展開的。

  PS:即使可以利用的cpu只有一個(早期的計算機確實如此),也能保證支持(偽)并發的能力。將一個單獨的cpu變成多個虛擬的cpu(多道技術:時間多路復用和空間多路復用+硬件上支持隔離),沒有進程的抽象,現代計算機將不復存在。

必備理論

#一 操作系統的作用:1:隱藏丑陋復雜的硬件接口,提供良好的抽象接口2:管理、調度進程,并且將多個進程對硬件的競爭變得有序#二 多道技術: 1.產生背景:針對單核,實現并發ps:現在的主機一般是多核,那么每個核都會利用多道技術有4個cpu,運行于cpu1的某個程序遇到io阻塞,會等到io結束再重新調度,會被調度到4個cpu中的任意一個,具體由操作系統調度算法決定。核心2.空間上的復用:如內存中同時有多道程序3.時間上的復用:復用一個cpu的時間片強調:遇到io切,占用cpu時間過長也切,核心在于切之前將進程的狀態保存下來,這樣才能保證下次切換回來時,能基于上次切走的位置繼續運行

二、多進程概念

1、進程:正在進行的一個過程或者說一個任務。而負責執行任務則是cpu。進程有如下三個狀態:

?

  其實在兩種情況下會導致一個進程在邏輯上不能運行,

  1. 進程掛起是自身原因,遇到I/O阻塞,便要讓出CPU讓其他進程去執行,這樣保證CPU一直在工作

  2. 與進程無關,是操作系統層面,可能會因為一個進程占用時間過多,或者優先級等原因,而調用其他的進程去使用CPU。

2、進程與程序的區別:程序僅僅只是一堆代碼而已,而進程指的是程序的運行過程。

? ? 強調:同一個程序執行兩次,那也是兩個進程,比如打開網易云音樂,雖然都是同一個軟件,但是一個可以播放音樂,一個可以播放mv。

舉例(單核+多道,實現多個進程的并發執行):egon在一個時間段內有很多任務要做:python備課的任務,寫書的任務,交女朋友的任務,王者榮耀上分的任務,  但egon同一時刻只能做一個任務(cpu同一時間只能干一個活),如何才能玩出多個任務并發執行的效果?egon備一會課,再去跟李杰的女朋友聊聊天,再去打一會王者榮耀....這就保證了每個任務都在進行中

3、并發與并行:

無論是并行還是并發,在用戶看來都是'同時'運行的,不管是進程還是線程,都只是一個任務而已,真是干活的是cpu,cpu來做這些任務,而一個cpu同一時刻只能執行一個任務

  并發:針對只有一個cpu執行多個進程的情況。是偽并行,即看起來是同時運行。單個cpu+多道技術就可以實現并發。

  并行:針對多個cpu執行多個進程的情況,并行也屬于并發。

  單核下,可以利用多道技術,多個核,每個核也都可以利用多道技術(多道技術是針對單核而言的

? ? ? ? ?有四個核,六個任務,這樣同一時間有四個任務被執行,假設分別被分配給了cpu1,cpu2,cpu3,cpu4,

? ? ? ? ?一旦任務1遇到I/O就被迫中斷執行,此時任務5就拿到cpu1的時間片去執行,這就是單核下的多道技術

? ? ? ? ?而一旦任務1的I/O結束了,操作系統會重新調用它(需知進程的調度、分配給哪個cpu運行,由操作系統說了算),可能被分配給四個cpu中的任意一個去執行

?

?三、同步\異步and阻塞\非阻塞

同步是指:發送方發出數據后,等接收方發回響應以后才發下一個數據包的通訊方式。

異步是指:發送方發出數據后,不等接收方發回響應,接著發送下個數據包的通訊方式。

同步:

#所謂同步,就是在發出一個功能調用時,在沒有得到結果之前,該調用就不會返回。
  按照這個定義,其實絕大多數函數都是同步調用。但是一般而言,我們在說同步、異步的時候,特指那些需要其他部件協作或者需要一定時間完成的任務。
#舉例: #1. multiprocessing.Pool下的apply #發起同步調用后,就在原地等著任務結束,根本不考慮任務是在計算還是在io阻塞,總之就是一股腦地等任務結束 #2. concurrent.futures.ProcessPoolExecutor().submit(func,).result() #3. concurrent.futures.ThreadPoolExecutor().submit(func,).result()

異步:

#異步的概念和同步相對。當一個異步功能調用發出后,調用者不能立刻得到結果。當該異步功能完成后,通過狀態、通知或回調來通知調用者。  
  如果異步功能用狀態來通知,那么調用者就需要每隔一定時間檢查一次,效率就很低(有些初學多線程編程的人,總喜歡用一個循環去檢查某個變量的值,這其實是一 種很嚴重的錯誤)。
  如果是使用通知的方式,效率則很高,因為異步功能幾乎不需要做額外的操作。至于回調函數,其實和通知沒太多區別。
#舉例: #1. multiprocessing.Pool().apply_async() #發起異步調用后,并不會等待任務結束才返回,相反,會立即獲取一個臨時結果(并不是最終的結果,可能是封裝好的一個對象)。 #2. concurrent.futures.ProcessPoolExecutor(3).submit(func,) #3. concurrent.futures.ThreadPoolExecutor(3).submit(func,)

阻塞:

#阻塞調用是指調用結果返回之前,當前線程會被掛起(如遇到io操作)。函數只有在得到結果之后才會將阻塞的線程激活。有人也許會把阻塞調用和同步調用等同起來,實際上他是不同的。
對于同步調用來說,很多時候當前線程還是激活的,只是從邏輯上當前函數沒有返回而已。
#舉例: #1. 同步調用:apply一個累計1億次的任務,該調用會一直等待,直到任務返回結果為止,但并未阻塞住(即便是被搶走cpu的執行權限,那也是處于就緒態); #2. 阻塞調用:當socket工作在阻塞模式的時候,如果沒有數據的情況下調用recv函數,則當前線程就會被掛起,直到有數據為止。

非阻塞:

#非阻塞和阻塞的概念相對應,指在不能立刻得到結果之前也會立刻返回,同時該函數不會阻塞當前線程。

小結:

#1. 同步與異步針對的是函數/任務的調用方式:同步就是當一個進程發起一個函數(任務)調用的時候,一直等到函數(任務)完成,而進程繼續處于激活狀態。而異步情況下是當一個進程發起一個函數(任務)調用的時候,不會等函數返回,而是繼續往下執行當,函數返回的時候通過狀態、通知、事件等方式通知進程任務完成。#2. 阻塞與非阻塞針對的是進程或線程:阻塞是當請求不能滿足的時候就將進程掛起,而非阻塞則不會阻塞當前進程

?

?

?四、多進程實現

1、multiprocessing模塊介紹

  Python提供了multiprocessing。multiprocessing模塊用來開啟子進程,并在子進程中執行我們定制的任務(比如函數),該模塊與多線程模塊threading的編程接口類似。?multiprocessing模塊的功能眾多:支持子進程、通信和共享數據、執行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件。? 需要再次強調的一點是:與線程不同,進程沒有任何共享狀態,進程修改的數據,改動僅限于該進程內。

2、Process類介紹:為創建進程的類

主要方法:

#p為子進程

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開啟的進程

主要屬性:

#p為子進程
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字符的字符串。這個鍵的用途是為涉及網絡連接的底層進程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)

3、創建并開啟子進程

  方式一:(常用)

from multiprocessing import Process
import timedef task(name):print('%s is running' %name)time.sleep(2)if __name__ == '__main__': #在windows系統下,開子進程的代碼必須寫到這一行下面p=Process(target=task,args=('egon',))p.start() #只是在給操作系統發了一個信號,讓操作系統去開進程(申請內存+拷貝父進程的地址空間)print('')

?

from multiprocessing import Process
import time
def work(name):print('%s is piaoing' %name)time.sleep(5)print('%s piao end' %name)
if __name__=='__main__':                 #windows系統必須加p=Process(target=work,args=('egon',))#args傳參必須是個元組括號內要加逗號,
只是在給操作系統發一個信號,讓操作系統去開進程
# # (申請內存,拷貝父進程的地址空間) p干的活是work 也可以以字典形式傳:kwargs={'name':'egon'} p.start()print('主進程')

方式二:run()? 名字是固定的

# multi 多 process進程
from multiprocessing import Process
import timeclass Myprocess(Process):  # 自己的類def __init__(self,name):super().__init__()  # 保證有父類的功能self.name=namedef run(self):print('%s is running' % self.name)time.sleep(2)if __name__ == '__main__':p = Myprocess('egon')p.start()  # 調的是p.run()print('')

?

from multiprocessing import Process
import time
class work(Process):def __init__(self,name):super(work, self).__init__()  # super()括號內的參數可以不用傳,,保證有父類的功能self.name=namedef run(self):                            #方法名run()不可以更換print('%s is piaoing' %self.name)time.sleep(5)print('%s piao end' %self.name)
if __name__=='__main__':                      #windows系統必須加p=work('egon')p.start()   # 調的是p.run()print('主進程')

?

為什么python運行的程序在系統是python.exe
python3 test.py ----> python.exe

?

當前進程ID : print(os.getpid())

?

解釋器pycharm(運行python)的進程id : print(os.getppid())

?

| 為管道符,在cmd輸tasklist? 是全部運行的進程,tasklist |findstr python 過濾出python

?

注意:進程的直接內存空間是彼此隔離的,如下例:

?

from multiprocessing import Process
n=100                 
#在windows系統中應該把全局變量定義在if __name__ == '__main__'之上 def work():global nn=0print('子進程內: ',n) if __name__ == '__main__':p=Process(target=work)p.start() #結果總為:0print('主進程內: ',n) #結果總為:100

?

4、socket并發編程實例

  可以實現多個客戶端與服務端進行交流。

服務端:

from socket import *
from multiprocessing import Processserver=socket(AF_INET,SOCK_STREAM)
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind(('127.0.0.1',8080))
server.listen(5)def talk(conn):while True:try:msg=conn.recv(1024)if not msg:breakconn.send(msg.upper())except Exception:breakif __name__ == '__main__':while True:conn,client_addr=server.accept()p=Process(target=talk,args=(conn,))p.start()

客戶端:

#多個客戶端
from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8080))
while True:msg=input('>>: ').strip()if not msg:continueclient.send(msg.encode('utf-8'))msg=client.recv(1024)print(msg.decode('utf-8'))

?

?

將進程干死:terminate

?

5、jion()方法詳解

  join方法的主要作用是等待子進程結束后執行主進程。

基于誰開的子進程誰來關

標準版
from multiprocessing import Process
import time,random
def func(name):print('%s is running'% name)time.sleep(random.randint(1,3))print('%s is runend'% name)if __name__ == '__main__':p1 = Process(target=func ,args=('egon',))p2 = Process(target=func ,args=('alex',))p3 = Process(target=func ,args=('lishi',))p4 = Process(target=func ,args=('jassin',))p1.start()p2.start()p3.start()p4.start()print('zhu')# 精簡版
from multiprocessing import Process
import time,randomdef piao(name):print('%s is piaoing' %name)time.sleep(random.randint(1,3))print('%s is done' %name)if __name__ == '__main__':p1 = Process(target=piao, args=('alex',))p2 = Process(target=piao, args=('wxx',))p3 = Process(target=piao, args=('yxx',))p_l = [p1, p2, p3]for p in p_l:p.start()for p in p_l:p.join()print('')

?

并行效果:

?

from multiprocessing import Process
import time
def piao(name):print('%s is piaoing' %name)time.sleep(3)print('%s is piao end' %name)
if __name__=='__main__':p1=Process(target=piao,args=('egon',))p2=Process(target=piao,args=('alex',))p3=Process(target=piao,args=('yuanhao',))p4=Process(target=piao,args=('wupeiqi',))start_time=time.time()p1.start()p2.start()p3.start()p4.start()p1.join()p2.join()p3.join()p4.join()end_time=time.time()print(end_time-start_time)                   #結果為:3.多print('主線程')                               #最后才被打印
egon is running
lishi is running
alex is running
jassin is running
egon is run end
lishi is run end
alex is run end
jassin is run end
3.2911880016326904
zhu

  解釋:p.join()是讓主線程等待p的結束,卡住的是主線程而絕非進程p,進程只要start就會在開始運行了,所以p1-p4.start()時,系統中已經有四個并發的進程了而我們p1.join()是在等p1結束,沒錯p1只要不結束主線程就會一直卡在原地,這也是問題的關鍵join是讓主線程等,而p1-p4仍然是并發執行的,p1.join的時候,其余p2,p3,p4仍然在運行,等p1.join結束,可能p2,p3,p4早已經結束了,這樣p2.join,p3.join.p4.join直接通過檢測,無需等待所以4個join花費的總時間仍然是耗費時間最長的那個進程運行的時間。

串行效果:

from multiprocessing import Process
import time
def run(name):print('%s is running' %name)time.sleep(3)print('%s is run end'%name)
if __name__ == '__main__':p1 = Process(target=run,args=('egon',))p2 = Process(target=run,args=('alex',))p3 = Process(target=run,args=('lishi',))p4 = Process(target=run,args=('jassin',))start_time = time.time()p1.start()p1.join()p2.start()p2.join()p3.start()p3.join()p4.start()p4.join()end_time = time.time()print(end_time - start_time)print('zhu')

?

結果:
egon is running
egon is run end
alex is running
alex is run end
lishi is running
lishi is run end
jassin is running
jassin is run end
12.697726249694824
zhu

?

?

解釋:以上p1,p2,p3,p4進程是上一個子進程執行完才逐一被啟動,形成串行效果。

?

六、進程池(Pool)

  多進程是實現并發的主要手段之一,但是通常會有如下問題:a.很明顯需要并發執行的任務通常要遠大于核數;b.一個操作系統不可能無限開啟進程,通常有幾個核就開幾個進程;c.進程開啟過多,效率反而會下降(開啟進程是需要占用系統資源的,而且開啟多余核數目的進程也無法做到并行)。

  Pool可以提供指定數量的進程,供用戶調用,當有新的請求提交到pool中時,如果池還沒有滿,那么就會創建一個新的進程用來執行該請求;但如果池中的進程數已經達到規定最大值,那么該請求就會等待,直到池中有進程結束,就重用進程池中的進程。執行任務的進程數始終位進程池中指定的那幾個。

1、同步調用

  同步調用:提交完任務后,在原地等待任務結束,一旦結束可以立刻拿到結果。

from concurrent.futures import ProcessPoolExecutor
import time,random,os
def run(name,n):print('%s is running %s' %(name,os.getpid()))time.sleep(1)return n**2
if __name__ == '__main__':p=ProcessPoolExecutor(4)for i in range(10):res=p.submit(run,'alex %s' %i,i).result() #同步調用#等進程執行完,并能得到結果,然后才開啟下一個進程,相當于串行 print(res)p.shutdown(wait=True)print('',os.getpid())

?

2、異步調用

  異步調用:提交完任務后,不會在原地等待任務結束,會繼續提交下一次任務,等到所有任務都結束后,才能get結果。

from concurrent.futures import ProcessPoolExecutor
import time,os
import random
def work(n):print('%s is working' %(os.getpid()))time.sleep(1)return n**2if __name__=='__main__':p=ProcessPoolExecutor(4)                              #從無到有開啟4個進程,而且一直是這4個進程objs=[]for i in range(10):objs=p.submin(work,'alex %s'%i,i)  #提交任務,不會在原地等結果
        objs.append(obj)
'''異步apply_async用法:如果使用異步提交的任務,主進程需要使用jion,等待進程池內任務都處理完,然后可以用get收集結果,否則,主進程結束,進程池可能還沒來得及執行,也就跟著一起結束了'''p.shutdown(wait = True)print('主',os.geipid())for obj in objs:print(obj.result())
''

?

'''
提交/調用任務的方式有兩種:同步調用:提交/調用一個任務,然后就在原地等著,等到該任務執行完畢拿到結果,再執行下一行代碼異步調用: 提交/調用一個任務,不在原地等著,直接執行下一行代碼,結果?'''# from multiprocessing import Process,Pool
from concurrent.futures import ProcessPoolExecutor
import time,random,osdef piao(name,n):print('%s is piaoing %s' %(name,os.getpid()))time.sleep(1)return n**2if __name__ == '__main__':p=ProcessPoolExecutor(4)objs=[]
for i in range(10):# res=p.submit(piao,'alex %s' %i,i).result() #同步調用# print(res)obj=p.submit(piao,'alex %s' %i,i) #異步調用
        objs.append(obj)for obj in objs:print(obj.result())# 關門+等# pool.close()# pool.join()p.shutdown(wait=True)print('',os.getpid())

******

from concurrent.futures import ProcessPoolExecutor
import time, random, osdef piao(name, n):print('%s is piaoing %s' % (name, os.getpid()))time.sleep(1)return n ** 2if __name__ == '__main__':p = ProcessPoolExecutor(4)objs = []start = time.time()for i in range(10):# res=p.submit(piao,'alex %s' %i,i).result() #同步調用# print(res)obj = p.submit(piao, 'alex %s' % i, i)  # 異步調用
        objs.append(obj)p.shutdown(wait=True)print('', os.getpid())for obj in objs:print(obj.result())stop = time.time()print(stop - start)

**

from concurrent.futures import ProcessPoolExecutor
import time,random,osdef piao(name):print('%s is piaoing %s' %(name,os.getpid()))time.sleep(random.randint(1,4))if __name__ == '__main__':p=ProcessPoolExecutor(4)for i in range(10):p.submit(piao,'alex %s' %i)p.shutdown(wait=True)  # shutdown 關門  wait=True 等print('',os.getpid())

?

轉載于:https://www.cnblogs.com/jassin-du/p/7921296.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/453569.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/453569.shtml
英文地址,請注明出處:http://en.pswp.cn/news/453569.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

面對職業誘惑,我們如何作出理性的選擇?

版權聲明:原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章原始出版、作者信息和本聲明。否則將追究法律責任。本文地址:http://blog.csdn.net/jobchanceleo/archive/2007/07/08/1682484.aspx 分享一個發生在我們身邊的案例&a…

xamarin怎么調用java的_XamarinSQLite教程在Xamarin.Android項目中使用數據庫

XamarinSQLite教程在Xamarin.Android項目中使用數據庫在Xamarin.Android項目中使用預設數據庫的具體操作步驟如下:(1)創建一個Xamarin.Android項目,如AndroidSQLiteDemo。(2)在AndroidSQLiteDemo項目的Resources文件夾下創建一個Raw文件夾。(3)將上一節中…

Selector的一些state使用

(一)Selector的基本狀態android:state_selected 控件選中狀態,可以為true或falseandroid:state_focused 控件獲得焦點狀態,可以為true或falseandroid:state_pressed 控件點擊狀態,可以為true或falseandroid:state_enabled 控件使能狀態&#…

服務框架及服務治理組件——業界調研

聲明:主要內容來自公司內部 對業界的調研,不一定恰當、準確、實時。 表格文字較多,APP閱讀體驗較差 團隊服務相關組件\方案通信框架監控負載均衡\路由是否開源騰訊完全自研;BG內部自治,每個BG有自己相應的解決方案,單獨…

在操作系統重啟后恢復應用程序的工作狀態

Windows 10 創意者更新之后,默認開啟了重啟后恢復應用程序狀態的功能。這是自 Vista 以來就提供的功能——Restart Manager。 應用程序實現這一功能只需要調用 RegisterApplicationRestart 即可。傳入兩個參數: 重啟后使用的命令行參數(例如當…

裁員感悟

好員工,別以為裁員與你無關(上) 版權聲明:原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章原始出版、作者信息和本聲明。否則將追究法律責任。本文地址:http://blog.csdn.net/jobchanceleo/archive/2007/05/26/…

php傳中文給Java_完美解決PHP中文亂碼(轉) - - JavaEye技術網站

PHP中文亂碼一般是字符集問題,編碼主要有下面幾個問題。一.首先是PHP網頁的編碼1.文件本身的編碼與網頁的編碼應匹配a.如果欲使用gb2312編碼,那么php要輸出頭:header(“Content-Type: text/html; charsetgb2312")&#xff0c…

CharSequence類

CharSequence是char類型的一個可讀序列,它本身是一個接口,CharBuffer、String、StringBuffer、StringBuilder這個四個類實現了這個接口。此接口對于不同種類的char序列提供統一的只讀訪問以下是這個函數的API 它只定義了四個方法 /*** This interface re…

程序員考核的五大死因

程序員考核的五大死因(上) 程序員作為企業開發力量的最核心資產,無疑得到公司從上至下的一致關注。開發是個智力密集型產業,程序開發的特點是,付出相同時間的情況下,兩個開發者之間的產能會相差十幾甚至幾…

java編寫螺旋矩陣講解_Java如何實現螺旋矩陣 Java實現螺旋矩陣代碼實例

本篇文章小編給大家分享一下Java實現螺旋矩陣代碼實例,小編覺得挺不錯的,現在分享給大家供大家參考,有需要的小伙伴們可以來看看。給定一個包含 m x n 個元素的矩陣(m 行, n 列),請按照順時針螺旋順序,返回矩陣中的所有…

Vue Axios的配置 (高仿餓了么)

export default {name: "app",components: {"v-header": header},data() {return {seller: {}};},created() {let _this this; // 讓this始終代表最初this指向的對象this.axios.get(../data.json).then(function(res) {_this.seller res.data.sellercons…

PagerAdapter學習

前言: ViewGroup可以實現很多功能,如簡單的頁面導航和頁面滑動等等。谷歌公司為我們提供ViewGroup的API。谷歌公司推薦我們把ViewGroup和Fragment一起使,如果一起使用的話,應該使用FragmentPagerAdapter和FragmentStatePagerAdapter來進行適配處理&#…

arXiv網站

arXiv 原先是由物理學家保羅金斯巴格在1991年建立的網站, 我們會將預稿上傳到arvix作為預收錄,因此這就是個可以證明論文原創性(上傳時間戳)的文檔收錄網站。轉載于:https://www.cnblogs.com/AntonioSu/p/8387324.html

加薪——愛你在心口難開

加薪——愛你在心口難開(1) (原文刊登于《程序員》雜志07年第4期) 剛過了春節的4月份,空氣中到處透著躁動的味道,“求職”、“招聘”不斷刺激著程序員們的耳鼓,其實大多數跳槽者如果能靜下心來審視自己一下&#xf…

java線程interrupt用法_Java線程中interrupt那點事 | 學步園

1.先看一下例子程序:import java.io.IOException;import java.net.ServerSocket;import javax.rmi.CORBA.Tie;/**author: ZhengHaibo*web: http://blog.csdn.net/nuptboyzhb*mail: zhb931706659126.com*2014-3-16 Nanjing,njupt,China*/public class TestThread {/*…

Kotlin Native新增Objective-C互操作能力以及對WebAssembly的支持

根據JetBrains技術主管Nikolay Igotti的介紹,Kotlin/Native 0.4已經可用于為iOS和macOS開發原生應用。此外該版本還為WebAssembly平臺提供了實驗性支持。 \\Kotlin/Native對iOS/macOS開發的支持,關鍵在于實現了與Objective-C的互操作性。JetBrains目前已…

TranslateAnimation動畫

眾所周知,TranslateAnimation是android中重要的一個動畫函數,很多時候我們都需要使用它來實現更好的UI效果,今天就簡單研究下這個TranslateAnimation。TranslateAnimation這個位移動畫主要有三個構造函數,對應著三種不同的參數形式…

maven項目使用jacoco插件檢測代碼覆蓋率詳細配置

使用maven構建項目&#xff08;java項目或者web項目都可以&#xff09; jacoco插件的配置參考官方網址&#xff1a;http://www.eclemma.org/jacoco/trunk/doc/maven.html &#xff08;1&#xff09;配置jacoco的依賴jar包 <dependency><groupId>org.jacoco</gro…

JAVA如何取得空list成員類型_String 類型的List作為一個成員變量保存,保存成功后取對象時報空指針...

異常&#xff1a;Caused by: java.lang.NullPointerException at org.litepal.crud.DataHandler.setToModelByReflection(DataHandler.java:1341) at org.litepal.crud.DataHandler.setGenericValueToModel(DataHandler.java:787) at org.litepal.crud.DataHandler.query(DataH…

C語言:幾種字符輸入函數的區別

幾種字符輸入函數的區別&#xff1a; 1、getche()函數:用于從鍵盤讀入一個字符并顯示&#xff0c;然后直接執行下一條語 句。2、getch()函數:用于從鍵盤中讀入一個字符&#xff0c;但不顯示在屏幕上&#xff0c;然后執行下一條語句。3、getchar()函數&#xff1a;用于從鍵盤讀…