談談多線程和進程,附上例題講解

  • 注重版權,轉載請註明原作者和原文鏈接
    作者:碼農BookSea
    原文鏈接:https://editor.csdn.net/md?articleId=105927139

本人剛寫博客不久,是個新人,望大家能給予一些鼓勵。 您的一個贊或者是評論區的一句話都將是對我最大的激勵。
在這裏插入圖片描述


1.線程和進程的區別

進程:進程是資源分配的最小單位
線程:程序執行的最小單位

計算級執行程序的時候,會創建相應的進程,進行資源分配的時候,是以進程爲單位進行相應的分配
每個進程都有相應的線程,再執行程序時,實際上是執行相應的一些列線程

地址空間:進程是有自己獨立的地址空間,每次啓動一個線程,都會分配對應的地址空間,來處理數據。線程是沒有獨立空間的,可以共享進程的地址空間

資源擁有
進程之間的資源是互相獨立的,同一個進程內的線程是可以共享本進程內的資源

執行過程;每個獨立的進程有一個程序運行的入口,我們回去順序的執行序列和程序入口。線程不能獨立執行,必須要依存再應用程序中,由應用程序提供多個線程執行控制

引入例子:比如說,A在一邊在跟男朋友聊天,一邊在跟我們上課。兩個動作同時進行,一個應用程序就是一個可執行文件,裏面包含了一個或者多個線程,一個或者多個線程中又包括了一個或者多個的進程

Window中的應用程序(軟件運行)會產生線程(一個應用程序可以對應多個線程)->
進程

程序中使用多個線程(併發),效率會提升,線程是我們可以控制程序中的最小的執行單位,我們的多線程其實就是多個線程在進程裏面去搶佔資源

例子:A昨天早上起牀(1h)-》洗漱(0.25h)-》吃早飯(0.25h)-》上課(8h)-》做作業(1h)-》打遊戲(2h)-》聊天(6h)-》睡覺 。。。每次都是按照順序執行,這個稱爲單線程
B:上課的時候在撩C-》做作業的時候也在撩C,在做一個動作的時候,同時也會在做另一個動作,那麼這個就稱爲多線程

2.具體問題;

兩個無限執行的循環
在這裏插入圖片描述

3.線程運行狀態

在這裏插入圖片描述

4.Java種實現線程的方式

1使用Thread類
在這裏插入圖片描述
在這裏插入圖片描述

啓動線程,調用的是start方法而不是run方法,start方法會調用start0,start0是一個native方法,JVM會自動執行

如果我們直接調用了start方法,線程就處於運行狀態麼?
先進入就緒狀態,如果JVM分配了資源,則進入運行狀態,如沒有分配到資源則處於就緒狀態 示例如下:

package com.etc.thread;

public class Thread01 extends Thread {

	
	public void run() {
		for(;1==1;) {
			try {
				sleep(500);//休眠
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("線程001");
		}
	}
	
}
package com.etc.thread;

public class Thread02 extends Thread {

	
	public void run() {
		for(;1==1;) {
				try {
					sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			System.out.println("線程002");
		}
	}
	
}
package com.etc.thread;

public class TestThread {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Thread01 th1=new  Thread01();
		Thread02 th2=new  Thread02();
		
		th1.start();
		th2.start();
	}

}

sleep用法
sleep(500)//sleep裏面存的是時間,單位是毫秒,作用是將當前線程休眠指定的時長

2 使用Runnable實現線程
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

3 使用callable實現線程
在這裏插入圖片描述

該接口下call方法有返回值
應用場景:
1:有返回結果,在某個線程的方法執行完成之後,需要告知調用者,結束了,例如我們想知道線程種代碼的執行效率
2;面試:通過實現Callable接口,重寫call方法,調用用到FutureTask

在這裏插入圖片描述

在這裏插入圖片描述

4 .FutureTask在這裏插入圖片描述

阻塞

堵車;下水道堵了

泡茶案例
兩個步驟:燒水(10s)-洗杯子(5個杯子,一個位子2s)(按照順序去執行) 20

兩個步驟:燒水(10s)-洗杯子(5個杯子,一個位子2s)(兩個線程並行執行)10

5. Thread和Runnable的區別和聯繫

1、Thread是一個類,Runnable是一個接口
2、Thread類實現了Runnable接口,重寫了run方法
3、Runnable是一個接口,定義一個類實現接口的同時還可以繼承其他類;
4、Runnable適合多個相同的程序代碼的線程去處理同一個資源,代碼可以被多個線程共享

6. 線程生命週期(必須要會描述)

在這裏插入圖片描述

新線程:當我們使用new關鍵字創建線程對象實例,那這個適合它只是作爲一個對象存在,JVM沒有爲他分配CPU資源,

就緒狀態:處於創建中的線程調用start方法將線程的狀態轉化爲就緒狀態,當前狀態已經得到了其他的系統資源,在等待CPU資源

運行狀態:就緒狀態得到CPU資源後進入運行狀態,執行run【call】方法中的代碼段

等待/阻塞:線程運行的過程中被剝奪資源或則和我們在等待某些事件,這個就進入等待/阻塞狀態,如supend()、sleep()被調用,或者線程使用wait()方法來等待條件變量,這個適合線程會釋放所有的資源,但是並不釋放鎖,所以很容易引起死鎖知道程序調用resume()方法回覆線程運行。等待事件結束後或者得足夠的資源就進入就緒態

死亡狀態:當線程運行結束【正常結束】由JVM收回線程所佔的資源

6 線程數據共享

練習:
要有5個售票點,用同一份數據,數據保持一致100張
使用Thread和Runnable兩種方式完成

Synchronized

在這裏插入圖片描述
在這裏插入圖片描述

以上代碼表示,當我們某個線程在使用這個方法的時候,其他線程無法使用當前方法,相當於給這個方法上了一個鎖

join方法

Join用法

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

如上使用join()不傳參時我們會先執行調用join的線程,只有在join的線程執行完了之後纔會執行其他線程

在這裏插入圖片描述

如果join方法後面有傳參,那麼表示我們其他線程需要等待當前線程XX毫米,在等待完這個時長之後,其他線程就會開始執行

在這裏插入圖片描述

如上所示,join如果在start的前面將會失效,此時線程還未啓動,此時使用join就不會有任何效果

t1調用了join方法,如果t1在規定的等待時間之前就完成了線程的運行,那麼我們的其他線程就可以不用繼續等待,可以直接進行線程的運行

7.線程同步和通信

創建一個用戶類需要有名字,性別,還有showPerson方法(展示用戶信息)、setPerson方法(將存入的用戶信息替換)

創建一個線程類,修改用戶信息。死循環一直去修改用戶信息,如果是奇數就存一個對象,如果是偶數就存另一個對象

創建第二個線程類。一直去循環輸出用戶的信息,。
創建一個測試類。執行我們的兩個線程

package com.etc.person;
//用戶類
public class Person {

	private String name;
	private String sex;
	
	
	public Person() {
		super();
	}
	public Person(String name, String sex) {
		super();
		this.name = name;
		this.sex = sex;
	}
	
	/**
	 * 獲取對象信息
	 */
	public void showPerson() {
		System.out.println(this.name+","+this.sex);
	}
	
	public void setPerson(String name,String sex) {
		this.name = name;
		this.sex = sex;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
}
package com.etc.person;

import java.util.Random;

public class ModifyPerson implements Runnable{

	private Person person;
	private int n;
	
	
	
	public ModifyPerson(Person person) {
		super();
		this.person = person;
	}



	@Override
	public void run() {
		while(true) {
			//隨機數去實例不同的用戶去賦值
			n=new Random().nextInt(100);
			if(n%2==0) {
				person.setPerson("A", "男");
			}else {
				person.setPerson("B", "女");
			}
			
		}
	}

}
package com.etc.person;

public class ShowPerson implements Runnable{

	private Person person;
	
	public ShowPerson(Person person) {
		super();
		this.person = person;
	}
	@Override
	public void run() {
		
		while(true) {
			person.showPerson();
		}
		
	}

}
package com.etc.person;

public class Test {

	public static void main(String[] args) {
		//創建Person對象
		Person person=new Person();
		//修改線程對象
		ModifyPerson md=new ModifyPerson(person);
		//顯示用戶信息線程對象
		ShowPerson sp=new ShowPerson(person);
		
		Thread th1=new Thread(md);
		th1.start();
		new Thread(sp).start();
	}
	
}

老鐵,如果確實對你有幫助請點個免費的贊鼓勵一下

白嫖不好,創作不易。各位的點贊就是我創作的最大動力,如果我有哪裏寫的不對,歡迎評論區留言進行指正,我們下篇文章見!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章