欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java必學(xué)必會(huì)之線程(1)

 更新時(shí)間:2015年12月03日 11:20:20   作者:孤傲蒼狼  
java必學(xué)必會(huì)之線程第一篇,介紹了線程的基本概念、線程的創(chuàng)建和啟動(dòng),想要學(xué)好java線程的朋友一定要好好閱讀這篇文章

一、線程的基本概念

  

線程理解:線程是一個(gè)程序里面不同的執(zhí)行路徑

  每一個(gè)分支都叫做一個(gè)線程,main()叫做主分支,也叫主線程。

  程只是一個(gè)靜態(tài)的概念,機(jī)器上的一個(gè).class文件,機(jī)器上的一個(gè).exe文件,這個(gè)叫做一個(gè)進(jìn)程。程序的執(zhí)行過程都是這樣的:首先把程序的代碼放到內(nèi)存的代碼區(qū)里面,代碼放到代碼區(qū)后并沒有馬上開始執(zhí)行,但這時(shí)候說明了一個(gè)進(jìn)程準(zhǔn)備開始,進(jìn)程已經(jīng)產(chǎn)生了,但還沒有開始執(zhí)行,這就是進(jìn)程,所以進(jìn)程其實(shí)是一個(gè)靜態(tài)的概念,它本身就不能動(dòng)。平常所說的進(jìn)程的執(zhí)行指的是進(jìn)程里面主線程開始執(zhí)行了,也就是main()方法開始執(zhí)行了。進(jìn)程是一個(gè)靜態(tài)的概念,在我們機(jī)器里面實(shí)際上運(yùn)行的都是線程。

  Windows操作系統(tǒng)是支持多線程的,它可以同時(shí)執(zhí)行很多個(gè)線程,也支持多進(jìn)程,因此Windows操作系統(tǒng)是支持多線程多進(jìn)程的操作系統(tǒng)。Linux和Uinux也是支持多線程和多進(jìn)程的操作系統(tǒng)。DOS就不是支持多線程和多進(jìn)程了,它只支持單進(jìn)程,在同一個(gè)時(shí)間點(diǎn)只能有一個(gè)進(jìn)程在執(zhí)行,這就叫單線程。

  CPU難道真的很神通廣大,能夠同時(shí)執(zhí)行那么多程序嗎?不是的,CPU的執(zhí)行是這樣的:CPU的速度很快,一秒鐘可以算好幾億次,因此CPU把自己的時(shí)間分成一個(gè)個(gè)小時(shí)間片,我這個(gè)時(shí)間片執(zhí)行你一會(huì),下一個(gè)時(shí)間片執(zhí)行他一會(huì),再下一個(gè)時(shí)間片又執(zhí)行其他人一會(huì),雖然有幾十個(gè)線程,但一樣可以在很短的時(shí)間內(nèi)把他們通通都執(zhí)行一遍,但對(duì)我們?nèi)藖碚f,CPU的執(zhí)行速度太快了,因此看起來就像是在同時(shí)執(zhí)行一樣,但實(shí)際上在一個(gè)時(shí)間點(diǎn)上,CPU只有一個(gè)線程在運(yùn)行。

學(xué)習(xí)線程首先要理清楚三個(gè)概念

1、進(jìn)程:進(jìn)程是一個(gè)靜態(tài)的概念
2、線程:一個(gè)進(jìn)程里面有一個(gè)主線程叫main()方法,是一個(gè)程序里面的,一個(gè)進(jìn)程里面不同的執(zhí)行路徑。
3、在同一個(gè)時(shí)間點(diǎn)上,一個(gè)CPU只能支持一個(gè)線程在執(zhí)行。因?yàn)镃PU運(yùn)行的速度很快,因此我們看起來的感覺就像是多線程一樣。
  什么才是真正的多線程?如果你的機(jī)器是雙CPU,或者是雙核,這確確實(shí)實(shí)是多線程。

二、線程的創(chuàng)建和啟動(dòng)

  

  在JAVA里面,JAVA的線程是通過java.lang.Thread類來實(shí)現(xiàn)的,每一個(gè)Thread對(duì)象代表一個(gè)新的線程。創(chuàng)建一個(gè)新線程出來有兩種方法:第一個(gè)是從Thread類繼承,另一個(gè)是實(shí)現(xiàn)接口runnable。VM啟動(dòng)時(shí)會(huì)有一個(gè)由主方法(public static void main())所定義的線程,這個(gè)線程叫主線程??梢酝ㄟ^創(chuàng)建Thread的實(shí)例來創(chuàng)建新的線程。你只要new一個(gè)Thread對(duì)象,一個(gè)新的線程也就出現(xiàn)了。每個(gè)線程都是通過某個(gè)特定的Thread對(duì)象所對(duì)應(yīng)的方法run()來完成其操作的,方法run()稱為線程體。

范例1:使用實(shí)現(xiàn)Runnable接口創(chuàng)建和啟動(dòng)新線程

開辟一個(gè)新的線程來調(diào)用run方法

package cn.galc.test;

public class TestThread1{
 public static void main(String args[]){
 Runner1 r1 = new Runner1();//這里new了一個(gè)線程類的對(duì)象出來
 //r1.run();//這個(gè)稱為方法調(diào)用,方法調(diào)用的執(zhí)行是等run()方法執(zhí)行完之后才會(huì)繼續(xù)執(zhí)行main()方法
 Thread t = new Thread(r1);//要啟動(dòng)一個(gè)新的線程就必須new一個(gè)Thread對(duì)象出來
 //這里使用的是Thread(Runnable target) 這構(gòu)造方法
 t.start();//啟動(dòng)新開辟的線程,新線程執(zhí)行的是run()方法,新線程與主線程會(huì)一起并行執(zhí)行
 for(int i=0;i<10;i++){
  System.out.println("maintheod:"+i);
 }
 }
}
/*定義一個(gè)類用來實(shí)現(xiàn)Runnable接口,實(shí)現(xiàn)Runnable接口就表示這個(gè)類是一個(gè)線程類*/
class Runner1 implements Runnable{
 public void run(){
 for(int i=0;i<10;i++){
  System.out.println("Runner1:"+i);
 }
 }
}


多線程程序執(zhí)行的過程如下所示:

 

不開辟新線程直接調(diào)用run方法

 

運(yùn)行結(jié)果如下:

 范例2:繼承Thread類,并重寫其run()方法創(chuàng)建和啟動(dòng)新的線程

package cn.galc.test;

/*線程創(chuàng)建與啟動(dòng)的第二種方法:定義Thread的子類并實(shí)現(xiàn)run()方法*/
public class TestThread2{
 public static void main(String args[]){
 Runner2 r2 = new Runner2();
 r2.start();//調(diào)用start()方法啟動(dòng)新開辟的線程
 for(int i=0;i<=10;i++){
  System.out.println("mainMethod:"+i);
 }
 }
}
/*Runner2類從Thread類繼承
通過實(shí)例化Runner2類的一個(gè)對(duì)象就可以開辟一個(gè)新的線程
調(diào)用從Thread類繼承來的start()方法就可以啟動(dòng)新開辟的線程*/
class Runner2 extends Thread{
 public void run(){//重寫run()方法的實(shí)現(xiàn)
 for(int i=0;i<=10;i++){
  System.out.println("Runner2:"+i);
 }
 }
}

  使用實(shí)現(xiàn)Runnable接口和繼承Thread類這兩種開辟新線程的方法的選擇應(yīng)該優(yōu)先選擇實(shí)現(xiàn)Runnable接口這種方式去開辟一個(gè)新的線程。因?yàn)榻涌诘膶?shí)現(xiàn)可以實(shí)現(xiàn)多個(gè),而類的繼承只能是單繼承。因此在開辟新線程時(shí)能夠使用Runnable接口就盡量不要使用從Thread類繼承的方式來開辟新的線程。

三、線程狀態(tài)轉(zhuǎn)換

  

3.1.線程控制的基本方法

  

3.2. sleep/join/yield方法介紹

  

sleep方法的應(yīng)用范例:

package cn.galc.test;

import java.util.*;

public class TestThread3 {
 public static void main(String args[]){
 MyThread thread = new MyThread();
 thread.start();//調(diào)用start()方法啟動(dòng)新開辟的線程
 try {
  /*Thread.sleep(10000);
  sleep()方法是在Thread類里面聲明的一個(gè)靜態(tài)方法,因此可以使用Thread.sleep()的格式進(jìn)行調(diào)用
  */
  /*MyThread.sleep(10000);
  MyThread類繼承了Thread類,自然也繼承了sleep()方法,所以也可以使用MyThread.sleep()的格式進(jìn)行調(diào)用
  */
  /*靜態(tài)方法的調(diào)用可以直接使用“類名.靜態(tài)方法名”
  或者“對(duì)象的引用.靜態(tài)方法名”的方式來調(diào)用*/
  MyThread.sleep(10000);
  System.out.println("主線程睡眠了10秒種后再次啟動(dòng)了");
  //在main()方法里面調(diào)用另外一個(gè)類的靜態(tài)方法時(shí),需要使用“靜態(tài)方法所在的類.靜態(tài)方法名”這種方式來調(diào)用
  /*
  所以這里是讓主線程睡眠10秒種
  在哪個(gè)線程里面調(diào)用了sleep()方法就讓哪個(gè)線程睡眠,所以現(xiàn)在是主線程睡眠了。
  */
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 //thread.interrupt();//使用interrupt()方法去結(jié)束掉一個(gè)線程的執(zhí)行并不是一個(gè)很好的做法
 thread.flag=false;//改變循環(huán)條件,結(jié)束死循環(huán)
 /**
  * 當(dāng)發(fā)生InterruptedException時(shí),直接把循環(huán)的條件設(shè)置為false即可退出死循環(huán),
  * 繼而結(jié)束掉子線程的執(zhí)行,這是一種比較好的結(jié)束子線程的做法
  */
 /**
  * 調(diào)用interrupt()方法把正在運(yùn)行的線程打斷
 相當(dāng)于是主線程一盆涼水潑上去把正在執(zhí)行分線程打斷了
 分線程被打斷之后就會(huì)拋InterruptedException異常,這樣就會(huì)執(zhí)行return語(yǔ)句返回,結(jié)束掉線程的執(zhí)行
 所以這里的分線程在執(zhí)行完10秒鐘之后就結(jié)束掉了線程的執(zhí)行
  */
 }
}

class MyThread extends Thread {
 boolean flag = true;// 定義一個(gè)標(biāo)記,用來控制循環(huán)的條件

 public void run() {
 /*
  * 注意:這里不能在run()方法的后面直接寫throw Exception來拋異常, 
  * 因?yàn)楝F(xiàn)在是要重寫從Thread類繼承而來的run()方法,重寫方法不能拋出比被重寫的方法的不同的異常。
  * 所以這里只能寫try……catch()來捕獲異常
  */
 while (flag) {
  System.out.println("==========" + new Date().toLocaleString() + "===========");
  try {
  /*
   * 靜態(tài)方法的調(diào)用格式一般為“類名.方法名”的格式去調(diào)用 在本類中聲明的靜態(tài)方法時(shí)調(diào)用時(shí)直接寫靜態(tài)方法名即可。 當(dāng)然使用“類名.方法名”的格式去調(diào)用也是沒有錯(cuò)的
   */
  // MyThread.sleep(1000);//使用“類名.方法名”的格式去調(diào)用屬于本類的靜態(tài)方法
  sleep(1000);//睡眠的時(shí)如果被打斷就會(huì)拋出InterruptedException異常
  // 這里是讓這個(gè)新開辟的線程每隔一秒睡眠一次,然后睡眠一秒鐘后再次啟動(dòng)該線程
  // 這里在一個(gè)死循環(huán)里面每隔一秒啟動(dòng)一次線程,每個(gè)一秒打印出當(dāng)前的系統(tǒng)時(shí)間
  } catch (InterruptedException e) {
  /*
   * 睡眠的時(shí)一盤冷水潑過來就有可能會(huì)打斷睡眠 
   * 因此讓正在運(yùn)行線程被一些意外的原因中斷的時(shí)候有可能會(huì)拋被打擾中斷(InterruptedException)的異常
   */
  return;
  // 線程被中斷后就返回,相當(dāng)于是結(jié)束線程
  }
 }
 }
}

運(yùn)行結(jié)果:

 join方法的使用范例:

package cn.galc.test;

public class TestThread4 {
 public static void main(String args[]) {
 MyThread2 thread2 = new MyThread2("mythread");
 // 在創(chuàng)建一個(gè)新的線程對(duì)象的同時(shí)給這個(gè)線程對(duì)象命名為mythread
 thread2.start();// 啟動(dòng)線程
 try {
  thread2.join();// 調(diào)用join()方法合并線程,將子線程mythread合并到主線程里面
  // 合并線程后,程序的執(zhí)行的過程就相當(dāng)于是方法的調(diào)用的執(zhí)行過程
 } catch (InterruptedException e) {
  e.printStackTrace();
 }
 for (int i = 0; i <= 5; i++) {
  System.out.println("I am main Thread");
 }
 }
}

class MyThread2 extends Thread {
 MyThread2(String s) {
 super(s);
 /*
  * 使用super關(guān)鍵字調(diào)用父類的構(gòu)造方法 
  * 父類Thread的其中一個(gè)構(gòu)造方法:“public Thread(String name)” 
  * 通過這樣的構(gòu)造方法可以給新開辟的線程命名,便于管理線程
  */
 }

 public void run() {
 for (int i = 1; i <= 5; i++) {
  System.out.println("I am a\t" + getName());
  // 使用父類Thread里面定義的
  //public final String getName(),Returns this thread's name.
  try {
  sleep(1000);// 讓子線程每執(zhí)行一次就睡眠1秒鐘
  } catch (InterruptedException e) {
  return;
  }
 }
 }
}

運(yùn)行結(jié)果:

yield方法的使用范例:

package cn.galc.test;

public class TestThread5 {
 public static void main(String args[]) {
 MyThread3 t1 = new MyThread3("t1");
 /* 同時(shí)開辟了兩條子線程t1和t2,t1和t2執(zhí)行的都是run()方法 */
 /* 這個(gè)程序的執(zhí)行過程中總共有3個(gè)線程在并行執(zhí)行,分別為子線程t1和t2以及主線程 */
 MyThread3 t2 = new MyThread3("t2");
 t1.start();// 啟動(dòng)子線程t1
 t2.start();// 啟動(dòng)子線程t2
 for (int i = 0; i <= 5; i++) {
  System.out.println("I am main Thread");
 }
 }
}

class MyThread3 extends Thread {
 MyThread3(String s) {
 super(s);
 }

 public void run() {
 for (int i = 1; i <= 5; i++) {
  System.out.println(getName() + ":" + i);
  if (i % 2 == 0) {
  yield();// 當(dāng)執(zhí)行到i能被2整除時(shí)當(dāng)前執(zhí)行的線程就讓出來讓另一個(gè)在執(zhí)行run()方法的線程來優(yōu)先執(zhí)行
  /*
   * 在程序的運(yùn)行的過程中可以看到,
   * 線程t1執(zhí)行到(i%2==0)次時(shí)就會(huì)讓出線程讓t2線程來優(yōu)先執(zhí)行 
   * 而線程t2執(zhí)行到(i%2==0)次時(shí)也會(huì)讓出線程給t1線程優(yōu)先執(zhí)行
   */
  }
 }
 }
}

運(yùn)行結(jié)果如下:

 以上就是本文的全部?jī)?nèi)容,對(duì)java線程進(jìn)行全面學(xué)習(xí),希望可以幫助到大家。

相關(guān)文章

  • SpringBoot加入Guava Cache實(shí)現(xiàn)本地緩存代碼實(shí)例

    SpringBoot加入Guava Cache實(shí)現(xiàn)本地緩存代碼實(shí)例

    這篇文章主要介紹了SpringBoot加入Guava Cache實(shí)現(xiàn)本地緩存代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • java反射超詳細(xì)講解

    java反射超詳細(xì)講解

    本文非常詳細(xì)的講解了java反射具體的內(nèi)容以及使用,java反射在現(xiàn)今的使用中很頻繁,希望此文可以幫大家解答疑惑,可以幫助大家理解
    2021-08-08
  • Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    Java并發(fā)編程之volatile與JMM多線程內(nèi)存模型

    這篇文章主要介紹了Java并發(fā)volatile與JMM多線程內(nèi)存模型,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • JAVA為什么要使用封裝及如何封裝經(jīng)典實(shí)例

    JAVA為什么要使用封裝及如何封裝經(jīng)典實(shí)例

    這篇文章主要給大家介紹了關(guān)于JAVA為什么要使用封裝及如何封裝的相關(guān)資料,封裝就是將屬性私有化,提供公有的方法訪問私有屬性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • Maven 命令行打包 和 pom.xml的常用配置詳解

    Maven 命令行打包 和 pom.xml的常用配置詳解

    這篇文章主要介紹了Maven 命令行打包 和 pom.xml的常用配置詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java通過關(guān)閉Socket終止線程

    Java通過關(guān)閉Socket終止線程

    這篇文章主要為大家詳細(xì)介紹了Java通過關(guān)閉Socket終止線程的相關(guān)代碼
    2017-04-04
  • Springboot 使用 JSR 303 對(duì) Controller 控制層校驗(yàn)及 Service 服務(wù)層 AOP 校驗(yàn) 使用消息資源文件對(duì)消息國(guó)際化

    Springboot 使用 JSR 303 對(duì) Controller 控制層校驗(yàn)及 Service 服務(wù)層 AOP 校驗(yàn)

    這篇文章主要介紹了Springboot 使用 JSR 303 對(duì) Controller 控制層校驗(yàn)及 Service 服務(wù)層 AOP 校驗(yàn) 使用消息資源文件對(duì)消息國(guó)際化的相關(guān)知識(shí),需要的朋友可以參考下
    2017-12-12
  • spring boot啟動(dòng)時(shí)加載外部配置文件的方法

    spring boot啟動(dòng)時(shí)加載外部配置文件的方法

    這篇文章主要給大家介紹了關(guān)于spring boot啟動(dòng)時(shí)加載外部配置文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-02-02
  • Java中spring boot 字符串判斷是否為空方法小結(jié)

    Java中spring boot 字符串判斷是否為空方法小結(jié)

    這篇文章主要介紹了Java中spring boot字符串判斷是否為空,通過安裝依賴,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-11-11
  • Spring AOP有多少個(gè)通知以及它們的執(zhí)行順序介紹

    Spring AOP有多少個(gè)通知以及它們的執(zhí)行順序介紹

    這篇文章主要介紹了Spring AOP有多少個(gè)通知以及它們的執(zhí)行順序,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11

最新評(píng)論