二、创建进程和线程
1、在 Windows 操作系統中創建進程
在 windows 操作系統中,我們創建一個進程通常就是打開某個應用軟件,這便在電腦中創建了一個進程。更原始一點的,我們在命令提示符中來做(我們以打開記事本這個進程為例):
第一步:windows+R,輸入cmd,打開 cmd 命令提示符
第二步:在命令提示符中輸入 notepad,按 Enter 鍵便會彈出記事本應用軟件
?
?PS:常用的windows 應用軟件命令
1、regedit:打開注冊表編輯器
2、control:打開控制面板
3、msconfig:打開系統配置
4、gpedit.msc:打開本地組策略
5、explorer:打開資源管理器
6、taskmgr:任務管理器
7、logoff:直接注銷計算機
8、osk:打開屏幕鍵盤
9、calc:打開計算器
10、mspaint:調出畫圖軟件
11、dxdiag:查看電腦詳細配置信息
12、mstsc:打開遠程桌面連接
13、systeminfo:查看計算機基本信息
14、notepad:打開記事本
回到頂部2、在 Java 中創建進程
第一種方法:通過 Runtime 類的 exec() 方法來創建進程
| 1 2 3 4 5 | public?class?Runtime extends?Object ①、表示當前進程所在的虛擬機實例,每個Java應用程序都有一個Runtime類的Runtime ,允許應用程序與運行應用程序的環境進行接口。 ②、由于任何進程只會運行與一個虛擬機實例當中,即只會產生一個虛擬機實例(底層源碼采用 單例模式) ③、當前運行時可以從getRuntime方法獲得。 |
?
?
由上面源碼可以看到,構造器私有化了,即外部我們不能 new 一個新的 Runtime 實例,而內部給了我們一個獲取 Runtime 實例的方法 getRuntime() 。
?
通過 Runtime 類創建一個 記事本的 進程
| 1 2 3 4 5 6 7 8 9 | public?class?ProcessTest { ????? ????public?static?void?main(String[] args)?throws?Exception { ????????Runtime run = Runtime.getRuntime(); ????????//打開記事本 ????????run.exec("notepad"); ????} } |
第二種方法:通過?ProcessBuilder 創建線程
| 1 2 3 | public?final?class?ProcessBuilder extends?Object<br>①、此類用于創建操作系統進程。 ②、每個ProcessBuilder實例管理進程屬性的集合。 start()方法使用這些屬性創建一個新的Process實例。 start()方法可以從同一實例重復調用,以創建具有相同或相關屬性的新子進程。 |
| 1 2 3 4 5 6 7 8 9 | public?class?ProcessTest { ????? ????public?static?void?main(String[] args)?throws?Exception { ????????//打開記事本 ????????ProcessBuilder pBuilder =?new?ProcessBuilder("notepad"); ????????pBuilder.start(); ????} } |
3、在 Java 中創建線程
第一種方法:繼承 Thread 類
| 1 2 3 | public?class?Thread extends?Object implements?Runnable |
?
步驟:1、定義一個線程類 A 繼承于 java.lang.Thread 類
2、在 A 類中覆蓋 Thread 類的 run() 方法
3、在 run() 方法中編寫需要執行的操作
4、在 main 方法(線程)中,創建線程對象,并啟動線程
創建線程類:A類 a = new A()類;
調用 start() 方法啟動線程:a.start();
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package?com.ys.thread; class?Thread1?extends?Thread{ ????@Override ????public?void?run() { ????????for(int?i =?0?; i <?10?;i++){ ????????????System.out.println("播放音樂"+i); ????????} ????} } public?class?ThreadTest { ????public?static?void?main(String[] args) { ????????for(int?i =?0?; i <?10?; i++){ ????????????System.out.println("玩游戲"+i); ????????????if(i==5){ ????????????????Thread1 th1 =?new?Thread1(); ????????????????th1.start(); ????????????} ????????} ????} } |
結果:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 玩游戲0 玩游戲1 玩游戲2 玩游戲3 玩游戲4 玩游戲5 玩游戲6 玩游戲7 玩游戲8 玩游戲9 播放音樂0 播放音樂1 播放音樂2 播放音樂3 播放音樂4 播放音樂5 播放音樂6 播放音樂7 播放音樂8 播放音樂9 |
注意:我們看結果,并不是出現 5 個先打游戲,然后在播放音樂,這是線程調度的結果,兩個線程同時在爭搶 CPU 的資源,即最后的結果,前面5個打游戲的必然先出現的,后面的啥時候出現播放音樂就看 CPU 怎么調度了,這是隨機的。我們不能干涉。
?
第二種方法:實現 Runnable 接口
| 1 2 | @FunctionalInterface public?interface?Runnable |
1、Runnable接口應由任何類實現,其實例將由線程執行。 該類必須定義一個無參數的方法,稱為run 。?
2、該接口旨在為希望在活動時執行代碼的對象提供一個通用協議。此類整個只有一個 run() 抽象方法
?
步驟:1、定義一個線程類 A 實現于 java.lang.Runnable 接口(注意:A類不是線程類,沒有 start()方法,不能直接 new A 的實例啟動線程)
2、在 A 類中覆蓋 Runnable 接口的 run() 方法
3、在 run() 方法中編寫需要執行的操作
4、在 main 方法(線程)中,創建線程對象,并啟動線程
創建線程類:Thread t = new Thread( new A類() ) ;
調用 start() 方法啟動線程:t.start();
?
?
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class?Runnable1?implements?Runnable{ ????@Override ????public?void?run() { ????????for(int?i =?0?; i <?10?;i++){ ????????????System.out.println("播放音樂"+i); ????????} ????} } public?class?RunnableTest { ????public?static?void?main(String[] args) { ????????for(int?i =?0?; i <?10?; i++){ ????????????System.out.println("玩游戲"+i); ????????????if(i==5){ ????????????????Thread th1 =?new?Thread(new?Runnable1()); ????????????????th1.start(); ????????????} ????????} ????} } |
?
?第三種方法:使用匿名內部類創建線程
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public?static?void?main(String[] args) { ????????for(int?i =?0?; i <?10?; i++){ ????????????System.out.println("玩游戲"+i); ????????????if(i==5){ ????????????????new?Thread(new?Runnable() { ????????????????????@Override ????????????????????public?void?run() { ????????????????????????for(int?i =?0?; i <?10?;i++){ ????????????????????????????System.out.println("播放音樂"+i); ????????????????????????} ????????????????????} ????????????????}).start(); ????????????} ????????} ????} |
注意:
1、啟動線程是調用 start() 方法,而不是 調用 run() 方法。
解析:run()方法:在本線程內調用run()方法,和其他方法沒有什么區別,可以重復多次調用;
start()方法:啟動一個線程,實際上還是調用該Runnable對象的run()方法。
打開 Thread 類的源碼,start()方法里面有一句:
private native void start0(); ?//native 關鍵字:本地程序調用
native關鍵字指的是Java本地接口調用,即是使用Java調用本地操作系統的函數功能完成一些特殊的操作,而這樣的代碼開發在Java中幾乎很少出現,因為Java的最大特點是可移植性,如果一個程序 只能在固定的操作系統上使用,那么可移植性就將徹底喪失,多線程的實現一定需要操作系統的支持,那么start0()方法實際上就和抽象方法很類似,沒有方法體,而是交給JVM 去實現,即在windows下的JVM可能使用A方法實現start0(),在linux下的JVM可能使用B方法實現start0(),在調用時并不會關心具體是何方式實現了start0()方法,只會關心最終的操作結果,交給 JVM去匹配了不同的操作系統。
?
2、不能多次啟動同一個線程,即多次調用 start() 方法,只能調用一次,否則報錯:
轉載于:https://www.cnblogs.com/zhoanghua/p/9292145.html
總結
- 上一篇: CentOS 7.4下使用yum安装My
- 下一篇: 慕课-北京理工大学 机器学习 大学生上