- 注重版權,轉載請註明原作者和原文鏈接
作者:碼農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();
}
}
老鐵,如果確實對你有幫助請點個免費的贊鼓勵一下
白嫖不好,創作不易。各位的點贊就是我創作的最大動力,如果我有哪裏寫的不對,歡迎評論區留言進行指正,我們下篇文章見!