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

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

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

一、線(xiàn)程的基本概念

  

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

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

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

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

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

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

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

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

  

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

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

開(kāi)辟一個(gè)新的線(xiàn)程來(lái)調(diào)用run方法

package cn.galc.test;

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


多線(xiàn)程程序執(zhí)行的過(guò)程如下所示:

 

不開(kāi)辟新線(xiàn)程直接調(diào)用run方法

 

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

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

package cn.galc.test;

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

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

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

  

3.1.線(xiàn)程控制的基本方法

  

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

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

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

運(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è)新的線(xiàn)程對(duì)象的同時(shí)給這個(gè)線(xiàn)程對(duì)象命名為mythread
 thread2.start();// 啟動(dòng)線(xiàn)程
 try {
  thread2.join();// 調(diào)用join()方法合并線(xiàn)程,將子線(xiàn)程mythread合并到主線(xiàn)程里面
  // 合并線(xiàn)程后,程序的執(zhí)行的過(guò)程就相當(dāng)于是方法的調(diào)用的執(zhí)行過(guò)程
 } 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)用父類(lèi)的構(gòu)造方法 
  * 父類(lèi)Thread的其中一個(gè)構(gòu)造方法:“public Thread(String name)” 
  * 通過(guò)這樣的構(gòu)造方法可以給新開(kāi)辟的線(xiàn)程命名,便于管理線(xiàn)程
  */
 }

 public void run() {
 for (int i = 1; i <= 5; i++) {
  System.out.println("I am a\t" + getName());
  // 使用父類(lèi)Thread里面定義的
  //public final String getName(),Returns this thread's name.
  try {
  sleep(1000);// 讓子線(xiàn)程每執(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í)開(kāi)辟了兩條子線(xiàn)程t1和t2,t1和t2執(zhí)行的都是run()方法 */
 /* 這個(gè)程序的執(zhí)行過(guò)程中總共有3個(gè)線(xiàn)程在并行執(zhí)行,分別為子線(xiàn)程t1和t2以及主線(xiàn)程 */
 MyThread3 t2 = new MyThread3("t2");
 t1.start();// 啟動(dòng)子線(xiàn)程t1
 t2.start();// 啟動(dòng)子線(xiàn)程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í)行的線(xiàn)程就讓出來(lái)讓另一個(gè)在執(zhí)行run()方法的線(xiàn)程來(lái)優(yōu)先執(zhí)行
  /*
   * 在程序的運(yùn)行的過(guò)程中可以看到,
   * 線(xiàn)程t1執(zhí)行到(i%2==0)次時(shí)就會(huì)讓出線(xiàn)程讓t2線(xiàn)程來(lái)優(yōu)先執(zhí)行 
   * 而線(xiàn)程t2執(zhí)行到(i%2==0)次時(shí)也會(huì)讓出線(xiàn)程給t1線(xiàn)程優(yōu)先執(zhí)行
   */
  }
 }
 }
}

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

 以上就是本文的全部?jī)?nèi)容,對(duì)java線(xiàn)程進(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í)例,文中通過(guò)示例代碼介紹的非常詳細(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多線(xiàn)程內(nèi)存模型

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

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

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

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

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

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

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

    這篇文章主要為大家詳細(xì)介紹了Java通過(guò)關(guān)閉Socket終止線(xiàn)程的相關(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)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-02-02
  • Java中spring boot 字符串判斷是否為空方法小結(jié)

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

    這篇文章主要介紹了Java中spring boot字符串判斷是否為空,通過(guò)安裝依賴(lài),結(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)論