當前位置:首頁 » 編程軟體 » windows多線程編程

windows多線程編程

發布時間: 2023-07-12 00:04:14

A. 關於C++多線程編程教學

在Windows NT和Windows 9x中,多線程的編程實現需要調用一系列的API函數,如CreateThread、ResumeThread等,比較麻煩而且容易出錯。我們使用Inprise公司的新一代RAD開發工具C++Builder,可以方便地實現多線程的編程。與老牌RAD工具Visual Basic和Delphi比,C++Builer不僅功能非常強大,而且它的編程語言是C++,對於系統開發語言是C的Windows系列操作系統,它具有其它編程語言無可比擬的優勢。利用C++Builder提供的TThread對象,多線程的編程變得非常簡便易用。那麼,如何實現呢?且待我慢慢道來,讓你體會一下多線程的強大功能。

1. 創建多線程程序:

首先,先介紹一下實現多線程的具體步驟。在C++Builder中雖然用Tthread對象說明了線程的概念,但是Tthread對象本身並不完整,需要在TThread下新建其子類,並重載Execute方法來使用線程對象。在C++Builder下可以很方便地實現這一點。

在C++Builder IDE環境下選擇菜單File|New,在New欄中選中Thread Object,按OK,接下來彈出輸入框,輸入TThread對象子類的名字MyThread,這樣C++Builder自動為你創建了一個名為TMyThread的TThread子類。同時編輯器中多了一個名為Unit2.cpp的單元,這就是我們創建的TMyThread子類的原碼,如下:

#include
#pragma hdrstop

#include 「Unit2.h」
#pragma package(smart_init)
//---------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall MyThread::UpdateCaption()
// {
// Form1->Caption = 「Updated in a thread」;
// }
//--------------------
__fastcall MyThread::MyThread(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//--------------------
void __fastcall MyThread::Execute()
{
//---- Place thread code here ----
}
//---------------------

其中的Execute()函數就是我們要在線程中實現的任務的代碼所在處。在原代碼中包含Unit2.cpp,這個由我們創建的TMyThread對象就可以使用了。使用時,動態創建一個TMyThread 對象,在構造函數中使用Resume()方法,那麼程序中就增加了一個新的我們自己定義的線程TMyThread,具體執行的代碼就是Execute()方法重載的代碼。要載入更多的線程,沒關系,只要繼續創建需要數量的TMyThread 對象就成。

B. windows環境,多線程情況下,C語言向文件寫入數據。

下面的程序,編譯之後,你可以運行很多個實例,目前我將文件寫在了D:\1.txt,每個程序寫1000行數據,這些值你可以自己更改(比如 寫在C:,每個程序寫10000行等),等程序都寫完後,你可以去文件中查看寫文件的結果。補充一下,我是在VC6.0環境中寫的,所以windows.h,如果你不是在這個環境中的話,可能需要修改一些定義,比如DWORD等。其他的API都是windows平台提供的API;
#include <stdio.h>
#include "windows.h"
int main()
{
//獲取進程ID,因為你希望是多個進程運行同時寫一個文件,所以,我們列印出進程ID
DWORD dwProcessID = GetCurrentProcessId();

//初始化我們要寫入文件中的內容,及該內容長度;
char szContent[100] = {0};
sprintf(szContent,"process[%u] write file\r\n",dwProcessID);
DWORD dwContentLen = strlen(szContent);

//創建互斥量,這樣可以進行進程間的互斥,當然用這個也可以做線程間的互斥
HANDLE hMutex = CreateMutex(NULL,FALSE,"MyFileMutex");
if (NULL == hMutex)
{
printf("[%u]Create/Open Mutex error!\r\n",dwProcessID);
return 1;
}

//創建或打開文件
HANDLE hFile = CreateFile("D:\\1.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ,NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_ARCHIVE,
NULL);
if (INVALID_HANDLE_VALUE == hFile)
{
printf("[%u]Creat/Open file error!\r\n",dwProcessID);
return 1;
}

//循環寫入文件
for(int i = 0; i < 1000 ; i++)
{
//等待臨界資源,即鎖定文件
WaitForSingleObject(hMutex,INFINITE);
printf("Process[%u] Get the signal\r\n",dwProcessID);
DWORD len = 0;

//因為是共享寫文件,即多個程序寫一個文件,所以一定要將文件指針偏移到尾部
SetFilePointer(hFile,0,NULL,FILE_END);

//寫入文件
BOOL rnt = WriteFile(hFile,szContent,dwContentLen,&len,NULL);
if (rnt == FALSE)
{
printf("Process[%u] Fail to write file\r\n",dwProcessID);
}

//釋放互斥量,解除鎖定
ReleaseMutex(hMutex);

//加個Sleep便於我們中間觀察結果
Sleep(30);
}
CloseHandle(hMutex);
CloseHandle(hFile);
return 0;
}

應你要求,我把AIP中的宏定義解釋如下:
HANDLE hFile = CreateFile("D:\\1.txt",
GENERIC_READ | GENERIC_WRITE,//表示程序對該文件有讀和寫的許可權
FILE_SHARE_WRITE | FILE_SHARE_READ,//表示可以多個程序共享讀和寫的許可權
NULL,
OPEN_ALWAYS,//表示打開該文件,如果該文件不存在,則創建該文件
FILE_ATTRIBUTE_ARCHIVE,//文件的屬性為存檔
NULL);

WaitForSingleObject(hMutex,INFINITE);
//INFINITE表示永遠等待,直到hMutex有信號為止

SetFilePointer(hFile,0,NULL,FILE_END);
//FILE_END表示從文件尾部開始偏移;實際此舉就是將文件指針偏移到文件尾部;

C. 淺談linux多線程編程和Windows多線程編程的異同

轉載自fychit創意空間 很早以前就想寫寫linux下多線程編程和windows下的多線程編程了,但是每當寫時又不知道從哪個地方寫起,怎樣把自己知道的東西都寫出來,下面我就談談linux多線程及線程同步,並將它和windows的多線程進行比較,看看他們之間有什麼相同點和不同的地方。

其實最開始我是搞windows下編程的,包括windows編程,windows 驅動,包括usb驅動,ndis驅動,pci驅動,1394驅動等等,同時也一條龍服務,做windows下的應用程序開發,後面慢慢的我又對linux開發產生比較深的興趣和愛好,就轉到搞linux開發了。在接下來的我還會寫一些博客,主要是寫linux編程和windows編程的區別吧,現在想寫的是linux下usb驅動和windows下usb驅動開發的區別,這些都是後話,等我將linux多線程和windows多線程講解完後,我再寫一篇usb驅動,談談windows 和linux usb驅動的東東。好了,言歸正傳。開始將多線程了。

首先我們講講為什麼要採用多線程編程,其實並不是所有的程序都必須採用多線程,有些時候採用多線程,性能還沒有單線程好。所以我們要搞清楚,什麼時候採用多線程。採用多線程的好處如下:

(1)因為多線程彼此之間採用相同的地址空間,共享大部分的數據,這樣和多進程相比,代價比較節儉,因為多進程的話,啟動新的進程必須分配給它獨立的地址空間,這樣需要數據表來維護代碼段,數據段和堆棧段等等。

(2)多線程和多進程相比,一個明顯的優點就是線程之間的通信了,對不同進程來說,它們具有獨立的數據空間,要進行數據的傳遞只能通過通信的方式進行,這種方式不僅費時,而且很不方便。但是對於多線程就不一樣了。他們之間可以直接共享數據,比如最簡單的方式就是共享全局變數。但是共享全部變數也要注意哦,呵呵,必須注意同步,不然後果你知道的。呵呵。

(3)在多cpu的情況下,不同的線程可以運行不同的cpu下,這樣就完全並行了。

反正我覺得在這種情況下,採用多線程比較理想。比如說你要做一個任務分2個步驟,你為提高工作效率,你可以多線程技術,開辟2個線程,第一個線程就做第一步的工作,第2個線程就做第2步的工作。但是你這個時候要注意同步了。因為只有第一步做完才能做第2步的工作。這時,我們可以採用同步技術進行線程之間的通信。

針對這種情況,我們首先講講多線程之間的通信,在windows平台下,多線程之間通信採用的方法主要有:

(1)共享全局變數,這種方法是最容易想到的,呵呵,那就首先講講吧,比如說吧,上面的問題,第一步要向第2步傳遞收據,我們可以之間共享全局變數,讓兩個線程之間傳遞數據,這時主要考慮的就是同步了,因為你後面的線程在對數據進行操作的時候,你第一個線程又改變了數據的內容,你不同步保護,後果很嚴重的。你也知道,這種情況就是讀臟數據了。在這種情況下,我們最容易想到的同步方法就是設置一個bool flag了,比如說在第2個線程還沒有用完數據前,第一個線程不能寫入。有時在2個線程所需的時間不相同的時候,怎樣達到最大效率的同步,就比較麻煩了。咱們可以多開幾個緩沖區進行操作。就像生產者消費者一樣了。如果是2個線程一直在跑的,由於時間不一致,緩沖區遲早會溢出的。在這種情況下就要考慮了,是不讓數據寫入還是讓數據覆蓋掉老的數據,這時候就要具體問題具體分析了。就此打住,呵呵。就是用bool變數控制同步,linux 和windows是一樣的。

既然講道了這里,就再講講其它同步的方法。同樣 針對上面的這個問題,共享全局變數同步問題。除了採用bool變數外,最容易想到的方法就是互斥量了。呵呵,也就是傳說中的加鎖了。windows下加鎖和linux下加鎖是類似的。採用互斥量進行同步,要想進入那段代碼,就先必須獲得互斥量。

linux上互斥量的函數是:

windows下互斥量的函數有:createmutex 創建一個互斥量,然後就是獲得互斥量waitforsingleobject函數,用完了就釋放互斥量ReleaseMutex(hMutex),當減到0的時候 內核會才會釋放其對象。下面是windows下與互斥的幾個函數原型。

HANDLE WINAPI CreateMutex(
__in LPSECURITY_ATTRIBUTES lpMutexAttributes,
__in BOOL bInitialOwner,
__in LPCTSTR lpName
);
可以可用來創建一個有名或無名的互斥量對象
第一參數 可以指向一個結構體SECURITY_ATTRIBUTES一般可以設為null;
第二參數 指當時的函數是不是感應感應狀態 FALSE為當前擁有者不會創建互斥
第三參數 指明是否是有名的互斥對象 如果是無名 用null就好。

DWORD WINAPI WaitForSingleObject(

__in HANDLE hHandle,

__in DWORD dwMilliseconds

);

第一個是 創建的互斥對象的句柄。第二個是 表示將在多少時間之後返回 如果設為宏INFINITE 則不會返回 直到用戶自己定義返回。

對於linux操作系統,互斥也是類似的,只是函數不同罷了。在linux下,和互斥相關的幾個函數也要閃亮登場了。

pthread_mutex_init函數:初始化一個互斥鎖;

pthread_mutex_destroy函數:注銷一個互斥鎖;

pthread_mutex_lock函數:加鎖,如果不成功,阻塞等待;

pthread_mutex_unlock函數:解鎖;

pthread_mutex_trylock函數:測試加鎖,如果不成功就立即返回,錯誤碼為EBUSY;

至於這些函數的用法,google上一搜,就出來了,呵呵,在這里不多講了。windows下還有一個可以用來保護數據的方法,也是線程同步的方式

就是臨界區了。臨界區和互斥類似。它們之間的區別是,臨界區速度快,但是它只能用來同步同一個進程內的多個線程。臨界區的獲取和釋放函數如下:

EnterCriticalSection() 進入臨界區; LeaveCriticalSection()離開臨界區。 對於多線程共享內存的東東就講到這里了。

(2)採用消息機制進行多線程通信和同步,windows下面的的消息機制的函數用的多的就是postmessage了。Linux下的消息機制,我用的較少,就不在這里說了,如果誰熟悉的,也告訴我,呵呵。

(3)windows下的另外一種線程通信方法就是事件和信號量了。同樣針對我開始舉得例子,2個線程同步,他們之間傳遞信息,可以採用事件(Event)或信號量(Semaphore),比如第一個線程完成生產的數據後,就必須告訴第2個線程,他已經把數據准備好了,你可以來取走了。第2個線程就把數據取走。呵呵,這里可以採用消息機制,當第一個線程准備好數據後,就直接postmessage給第2個線程,按理說採用postmessage一個線程就可以搞定這個問題了。呵呵,不是重點,省略不講了。

對於linux,也有類似的方法,就是條件變數了,呵呵,這里windows和linux就有不同了。要特別講講才行。

對於windows,採用事件和信號量同步時候,都會使用waitforsingleobject進行等待的,這個函數的第一個參數是一個句柄,在這里可以是Event句柄,或Semaphore句柄,第2個參數就是等待的延遲,最終等多久,單位是ms,如果這個參數為INFINITE,那麼就是無限等待了。釋放信號量的函數為ReleaseSemaphore();釋放事件的函數為SetEvent。當然使用這些東西都要初始化的。這里就不講了。Msdn一搜,神馬都出來了,呵呵。神馬都是浮雲!

對於linux操作系統,是採用條件變數來實現類似的功能的。Linux的條件變數一般都是和互斥鎖一起使用的,主要的函數有:

pthread_mutex_lock ,

pthread_mutex_unlock,

pthread_cond_init

pthread_cond_signal

pthread_cond_wait

pthread_cond_timewait

D. 高手進,關於C語言在windows上建立多線程的問題(VC6.0上實現)

東西,往往實例才是最讓人感興趣的,老是學基礎理論,不動手,感覺沒有成就感,呵呵。

下面先來一個實例。我們通過創建兩個線程來實現對一個數的遞加。
或許這個實例沒有實際運用的價值,但是稍微改動一下,我們就可以用到其他地方去拉。

下面是我們的代碼:

/*thread_example.c : c multiple thread programming in linux
*author : falcon
*E-mail : [email protected]
*/
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define MAX 10

pthread_t thread[2];
pthread_mutex_t mut;
int number="0", i;

void *thread1()
{
printf ("thread1 : I'm thread 1\n");

for (i = 0; i < MAX; i++)
{
printf("thread1 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(2);
}

printf("thread1 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}

void *thread2()
{
printf("thread2 : I'm thread 2\n");

for (i = 0; i < MAX; i++)
{
printf("thread2 : number = %d\n",number);
pthread_mutex_lock(&mut);
number++;
pthread_mutex_unlock(&mut);
sleep(3);
}

printf("thread2 :主函數在等我完成任務嗎?\n");
pthread_exit(NULL);
}

void thread_create(void)
{
int temp;
memset(&thread, 0, sizeof(thread)); //comment1
/*創建線程*/
if((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0) //comment2
printf("線程1創建失敗!\n");
else
printf("線程1被創建\n");

if((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0) //comment3
printf("線程2創建失敗");
else
printf("線程2被創建\n");
}

void thread_wait(void)
{
/*等待線程結束*/
if(thread[0] !=0) { //comment4
pthread_join(thread[0],NULL);
printf("線程1已經結束\n");
}
if(thread[1] !=0) { //comment5
pthread_join(thread[1],NULL);
printf("線程2已經結束\n");
}
}

int main()
{
/*用默認屬性初始化互斥鎖*/
pthread_mutex_init(&mut,NULL);

printf("我是主函數哦,我正在創建線程,呵呵\n");
thread_create();
printf("我是主函數哦,我正在等待線程完成任務阿,呵呵\n");
thread_wait();

return 0;
}

下面我們先來編譯、執行一下

引文:

falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/c/code/ftp$ ./thread_example
我是主函數哦,我正在創建線程,呵呵
線程1被創建
線程2被創建
我是主函數哦,我正在等待線程完成任務阿,呵呵
thread1 : I'm thread 1
thread1 : number = 0
thread2 : I'm thread 2
thread2 : number = 1
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
thread1 : number = 6
thread1 : number = 7
thread2 : number = 8
thread1 : number = 9
thread2 : number = 10
thread1 :主函數在等我完成任務嗎?
線程1已經結束
thread2 :主函數在等我完成任務嗎?
線程2已經結束

實例代碼里頭的注釋應該比較清楚了吧,下面我把網路上介紹上面涉及到的幾個函數和變數給引用過來。

引文:

線程相關操作

一 pthread_t

pthread_t在頭文件/usr/include/bits/pthreadtypes.h中定義:
typedef unsigned long int pthread_t;
它是一個線程的標識符。

二 pthread_create

函數pthread_create用來創建一個線程,它的原型為:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
void *(*__start_routine) (void *), void *__arg));
第一個參數為指向線程標識符的指針,第二個參數用來設置線程屬性,第三個參數是線程運行函數的起始地址,最後一個參數是運行函數的參數。這里,我們的函數thread不需要參數,所以最後一個參數設為空指針。第二個參數我們也設為空指針,這樣將生成默認屬性的線程。對線程屬性的設定和修改我們將在下一節闡述。當創建線程成功時,函數返回0,若不為0則說明創建線程失敗,常見的錯誤返回代碼為EAGAIN和EINVAL。前者表示系統限制創建新的線程,例如線程數目過多了;後者表示第二個參數代表的線程屬性值非法。創建線程成功後,新創建的線程則運行參數三和參數四確定的函數,原來的線程則繼續運行下一行代碼。

三 pthread_join pthread_exit

函數pthread_join用來等待一個線程的結束。函數原型為:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第一個參數為被等待的線程標識符,第二個參數為一個用戶定義的指針,它可以用來存儲被等待線程的返回值。這個函數是一個線程阻塞的函數,調用它的函數將一直等待到被等待的線程結束為止,當函數返回時,被等待線程的資源被收回。一個線程的結束有兩種途徑,一種是象我們上面的例子一樣,函數結束了,調用它的線程也就結束了;另一種方式是通過函數pthread_exit來實現。它的函數原型為:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯一的參數是函數的返回代碼,只要pthread_join中的第二個參數thread_return不是NULL,這個值將被傳遞給 thread_return。最後要說明的是,一個線程不能被多個線程等待,否則第一個接收到信號的線程成功返回,其餘調用pthread_join的線程則返回錯誤代碼ESRCH。
在這一節里,我們編寫了一個最簡單的線程,並掌握了最常用的三個函數pthread_create,pthread_join和pthread_exit。下面,我們來了解線程的一些常用屬性以及如何設置這些屬性。

互斥鎖相關

互斥鎖用來保證一段時間內只有一個線程在執行一段代碼。

一 pthread_mutex_init

函數pthread_mutex_init用來生成一個互斥鎖。NULL參數表明使用默認屬性。如果需要聲明特定屬性的互斥鎖,須調用函數 pthread_mutexattr_init。函數pthread_mutexattr_setpshared和函數 pthread_mutexattr_settype用來設置互斥鎖屬性。前一個函數設置屬性pshared,它有兩個取值, PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用來不同進程中的線程同步,後者用於同步本進程的不同線程。在上面的例子中,我們使用的是默認屬性PTHREAD_PROCESS_ PRIVATE。後者用來設置互斥鎖類型,可選的類型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、 PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它們分別定義了不同的上所、解鎖機制,一般情況下,選用最後一個默認屬性。

二 pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

pthread_mutex_lock聲明開始用互斥鎖上鎖,此後的代碼直至調用pthread_mutex_unlock為止,均被上鎖,即同一時間只能被一個線程調用執行。當一個線程執行到pthread_mutex_lock處時,如果該鎖此時被另一個線程使用,那此線程被阻塞,即程序將等待到另一個線程釋放此互斥鎖。

注意:

1 需要說明的是,上面的兩處sleep不光是為了演示的需要,也是為了讓線程睡眠一段時間,讓線程釋放互斥鎖,等待另一個線程使用此鎖。下面的參考資料1里頭說明了該問題。但是在linux下好像沒有pthread_delay_np那個函數(我試了一下,提示沒有定義該函數的引用),所以我用了sleep來代替,不過參考資料2中給出另一種方法,好像是通過pthread_cond_timedwait來代替,里頭給出了一種實現的辦法。

2 請千萬要注意里頭的注釋comment1-5,那是我花了幾個小時才找出的問題所在。
如果沒有comment1和comment4,comment5,將導致在pthread_join的時候出現段錯誤,另外,上面的comment2和comment3是根源所在,所以千萬要記得寫全代碼。因為上面的線程可能沒有創建成功,導致下面不可能等到那個線程結束,而在用pthread_join的時候出現段錯誤(訪問了未知的內存區)。另外,在使用memset的時候,需要包含string.h頭文件哦

E. 淺談linux 多線程編程和 windows 多線程編程的異同

linux下線程的實現,linux的線程編程有兩個庫pthread和pth,對於pthread的實現是內核方式的實現,每個線程在kernel中都有task結構與之對應,也就是說用ps命令行是可以看見多個線程,線程的調度也是由內核中的schele進行的。
再來看看Windows的多線程,Windows NT和Windows95是一個搶先型多任務、多線程操作系統。因為它使用搶先型的多任務,所以它擁有與UNIX同樣平滑的處理和進程獨立。多線程就更進一步。一個獨立的程序默認是使用一個線程,不過它可以將自己分解為幾個獨立的線程來執行,例如,其中的一個線程可以發送一個文件到列印機,而另一個可以響應用戶的輸入。這個簡單的程序設計修改可以明顯減少用戶等待的時間,讓用戶無需擔心長時間的計算、重繪屏幕、文件讀寫等帶來的不便。
多線程還可以讓你從許多高端的多處理器NT機器中得到好處。例如,你購買了一個高級的RISC機器,可以使用多達10個CPU晶元,但在開始的時候你只購買了一個CPU。你寫了一個簡單的Mandelbrot set程序,你發現需要15秒的時間來重新繪制Mandelbrot set的畫面。
那麼,Windows平台的線程和類Unix平台(包括Linux)的進程的區別是什麼呢?
熟悉WIN32編程的人一定知道,WIN32的進程管理方式與UNIX上有著很大區別,在UNIX里,只有進程的概念,但在WIN32里卻還有一個「線程」的概念,那麼UNIX和WIN32在這里究竟有著什麼區別呢?
UNIX里的fork是七十年代UNIX早期的開發者經過長期在理論和實踐上的艱苦探索後取得的成果,一方面,它使操作系統在進程管理上付出了最小的代價,另一方面,又為程序員提供了一個簡潔明了的多進程方法。
WIN32里的進程/線程是繼承自OS/2的。在WIN32里,「進程」是指一個程序,而「線程」是一個「進程」里的一個執行「線索」。從核心上講,WIN32的多進程與UNIX並無多大的區別,在WIN32里的線程才相當於UNIX的進程,是一個實際正在執行的代碼。但是,WIN32里同一個進程里各個線程之間是共享數據段的。這才是與UNIX的進程最大的不同。
對於多任務系統,共享數據區是必要的,但也是一個容易引起混亂的問題,在WIN32下,一個程序員很容易忘記線程之間的數據是共享的這一情況,一個線程修改過一個變數後,另一個線程卻又修改了它,結果引起程序出問題。但在UNIX下,由於變數本來並不共享,而由程序員來顯式地指定要共享的數據,使程序變得更清晰與安全。

熱點內容
什麼是資源為什麼要研究資源配置 發布:2025-02-07 08:25:19 瀏覽:87
釣魚網站源碼製作 發布:2025-02-07 08:23:54 瀏覽:139
mac運行fl需要什麼配置 發布:2025-02-07 08:15:45 瀏覽:573
安卓怎麼做都比不了蘋果 發布:2025-02-07 08:12:47 瀏覽:238
怎麼給物理機配置ip地址 發布:2025-02-07 08:01:37 瀏覽:139
三國志13未加密 發布:2025-02-07 07:54:37 瀏覽:926
馬斯克中國訪問 發布:2025-02-07 07:54:29 瀏覽:102
資料庫有表 發布:2025-02-07 07:50:49 瀏覽:29
基於nginx搭建圖片伺服器原理 發布:2025-02-07 07:44:18 瀏覽:449
java等待 發布:2025-02-07 07:28:24 瀏覽:613