二、創建進程和線程
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() 方法,只能調用一次,否則報錯:
二、創建進程和線程