java創建多線程&創建進程


概述

並發和並行是即相似又有區別:

  • 並行:指兩個或多個事件在同一時刻發生;
  • 並發:指兩個或多個事件在同一時間段內發生。

進程是指一個內存中運行中的應用程序。每個進程都有自己獨立的一塊內存空間,一個應用程序可以同時啟動多個進程。比如在Windows系統中,一個運行的abc.exe就是一個進程。
那么我們此時就可以處理同時玩游戲和聽音樂的問題了,我們可以設計成兩個程序,一個專門負責玩游戲,一個專門負責聽音樂。
但是問題來了,要是要設計一個植物大戰僵屍游戲,我得開N個進程才能完成多個功能,這樣的設計顯然是不合理的。
更何況大多數操作系統都不需要一個進程訪問其他進程的內存空間,也就是說進程之間的通信很不方便。
此時我們得引入“線程”這門技術,來解決這個問題。

線程是指進程中的一個執行任務(控制單元),一個進程可以同時並發運行多個線程,如:多線程下載軟件。
一個進程至少有一個線程,為了提高效率,可以在一個進程中開啟多個執行任務,即多線程。
多進程:操作系統中同時運行的多個程序。
多線程:在同一個進程中同時運行的多個任務。
我們查看Windows環境下的任務管理器:
在操作系統中允許多個任務,每一個任務就是一個進程,每一個進程也可以同時執行多個任務,每一個任務就是線程。

多線程作為一種多任務、並發的工作方式,當然有其存在優勢:

  • 進程之前不能共享內存,而線程之間共享內存(堆內存)則很簡單。
  • 系統創建進程時需要為該進程重新分配系統資源,創建線程則代價小很多,因此實現多任務並發時,多線程效率更高.
  • Java語言本身內置多線程功能的支持,而不是單純第作為底層系統的調度方式,從而簡化了多線程編程.

用java語言創建進程

import java.io.IOException;
//如何用java語言開啟一個進程
public class ProcessDemo {
	public static void main(String[] args) throws IOException{
		//方式一:使用Runtime的exec方法
		Runtime.getRuntime().exec("notepad");
		//方式二:使用ProcessBuilder類中的start方法
		ProcessBuilder pb = new ProcessBuilder("notepad");
		pb.start();
	}
}

創建和啟動線程

方式一:繼承Thread類

  1. 自定義類繼承於Thread類,那么該自定義類就是線程類;

2.覆寫run方法,將線程運行的代碼存放在run中;

3.創建自定義類的對象,即線程對象;

4.調用線程對象的start方法,啟動線程。

package thread_create;
//繼承方式 創建和啟動線程
class MusicThread extends Thread{      //MusicThread是線程子類
	public void run() {               //子類必須重寫run()方法
		for(int i = 0 ;i < 50;i++)
		{
			System.out.println("聽音樂"+i);
		}
	}
	
}
public class ExtendsThreadDemo {
	public static void main(String[] args){
		for(int i = 0 ;i < 50;i++)
		{
			System.out.println("玩游戲"+i);
			if( i == 10){
				MusicThread t = new MusicThread();  //創建線程子類的實例
				t.start(); //底層也調用了run();  啟動線程
			}
		}
			
	}
}

方式二:實現Runnable接口

1.自定義類實現Runnable接口;

2.覆寫run方法,線程運行的代碼存放在run中;

3.通過Thread類創建線程對象,並將實現了Runnable接口的實現類對象作為參數傳遞給Thread類的構造器。

4.Thread類對象調用start方法,啟動線程。

class MusicRunnable implements java.lang.Runnable{         //注意MusicRunnable類不是線程類或者線程子類
	public void run() {									   //接口的實現必須覆蓋方法。				
		for(int i = 0 ;i < 50;i++)
		{
			System.out.println("聽音樂"+i);
		}
	}
}
public class ImplementsRunnableDemo {
	public static void main(String[] args){
		for(int i = 0 ;i < 50;i++)
		{
			System.out.println("玩游戲"+i);
			if( i == 10){
				Runnable t = new MusicRunnable();        //啟動線程必須用線程類對象調用start();
				new Thread(t).start();             //類Thread的一個構造器中Thread(Runnable target)分配新的 Thread 對象。
			}
		}
	}
}

對比兩種方法(吃蘋果比賽)

1、繼承Thread類

/**
 * 	案例:存在50個蘋果,現在有請三個童鞋(小A,小B,小C)上台表演吃蘋果.
 * 		因為A,B,C三個人可以同時吃蘋果,此時得使用多線程技術來實現這個案例.
 *
 *       此處程序不合理,ABC每個線程都執行50次,即ABC每個人都吃一次編號50的蘋果
 */
class Person extends Thread{
	private  int num= 50;
	Person(String name){
		super(name);
	}
	public void run() {
		for(int i = 0;i < 50;i++){
		if(num > 0)	
		System.out.println(super.getName()+"吃了第"+num--+"個蘋果");
		}
	}	
}
//使用繼承Thread的方式創建線程
public class ExtendsDemo {
	public static void main(String[] args){
		Person p1 = new Person("A");
		p1.start();
		Person p2 = new Person("B");
		p2.start();
		Person p3 = new Person("C");
		p3.start();
	}
}

2、實現Runnable接口

class Apple implements Runnable{
	private int num = 50;
	public void run(){
		for(int i = 0; i< 50 ;i++){
			if(num > 0){
				System.out.println(Thread.currentThread().getName()+"吃了第"+num--+"個蘋果");
			}//Thread.currentThread()   返回對當前正在執行的線程對象的引用。
		}
	}
}
//使用實現Runnable接口的方式,這種方法可以解決此問題
public class ImplementsDemo {
	public static void main(String[] args){
		Runnable r = new Apple();
		new Thread(r,"A").start();
		new Thread(r,"B").start();
		new Thread(r,"C").start();
	}
}

對比

繼承方式:

  • java中類是單繼承的,如果繼承了Thread,該類就不能再有其他的直接父類
  • 從操作上分析,繼承方式更簡單,獲取線程的名字也簡單(操作上,簡單)
  • 從多線程共享一個資源上分析,繼承方式不能做到

實現方式

  • java中類可以實現接口,此時該類還可以繼承其他類,並且可以實現接口(設計上,更優雅)
  • 從操作上分析,實現方式稍微復雜點,獲取線程的名字比較復雜,得使用currentThread()獲取當前線程的引用。
  • 從多線程共享一個資源上分析,實現方式可以做到


免責聲明!

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



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