Java 多線程詳解(二)------如何創建進程和線程


  在上一篇博客中,我們已經介紹了並發和並行的區別,以及進程和線程的理解,那么在Java 中如何創建進程和線程呢?

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() 方法來創建進程

public class Runtime
extends Object
①、表示當前進程所在的虛擬機實例,每個Java應用程序都有一個Runtime類的Runtime ,允許應用程序與運行應用程序的環境進行接口。
②、由於任何進程只會運行與一個虛擬機實例當中,即只會產生一個虛擬機實例(底層源碼采用 單例模式)
③、當前運行時可以從getRuntime方法獲得。 

   

 

  由上面源碼可以看到,構造器私有化了,即外部我們不能 new 一個新的 Runtime 實例,而內部給了我們一個獲取 Runtime 實例的方法 getRuntime() 。

 

通過 Runtime 類創建一個 記事本的 進程

public class ProcessTest {
	
	public static void main(String[] args) throws Exception {
		Runtime run = Runtime.getRuntime();
		//打開記事本
		run.exec("notepad");
	}

}

  

第二種方法:通過 ProcessBuilder 創建進程

public final class ProcessBuilder
extends Object
①、此類用於創建操作系統進程。 ②、每個ProcessBuilder實例管理進程屬性的集合。 start()方法使用這些屬性創建一個新的Process實例。 start()方法可以從同一實例重復調用,以創建具有相同或相關屬性的新子進程。

public class ProcessTest {
	
	public static void main(String[] args) throws Exception {
		//打開記事本
		ProcessBuilder pBuilder = new ProcessBuilder("notepad");
		pBuilder.start();
	}

} 

3、在 Java 中創建線程

第一種方法:繼承 Thread 類

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();

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();
			}
		}
	}

}

  結果:

玩游戲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 接口

@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();

 

 

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();
			}
		}
	}

}

  

 

 第三種方法:使用匿名內部類創建線程

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() 方法,只能調用一次,否則報錯:

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM