java高級考試題復(fù)習(xí)題4-Java多線程題庫

一、 填空題

1.處于運(yùn)行狀態(tài)的線程在某些情況下,如執(zhí)行了sleep(睡眠)方法,或等待I/O設(shè)備等資源,將讓出CPU并暫時(shí)停止自己的運(yùn)行,進(jìn)入____阻塞_____狀態(tài)。
2.處于新建狀態(tài)的線程被啟動(dòng)后,將進(jìn)入線程隊(duì)列排隊(duì)等待CPU,此時(shí)它已具備了運(yùn)行條件,一旦輪到享用CPU資源就可以獲得執(zhí)行機(jī)會(huì)。上述線程是處于 就緒 狀態(tài)。
解析: 線程的生命周期—五個(gè)階段

    新建狀態(tài)---- new關(guān)鍵字創(chuàng)建線程對象

    就緒狀態(tài)---- start()方法運(yùn)行之前

    運(yùn)行狀態(tài)---- run()方法的運(yùn)行

    堵塞狀態(tài)--- interrupt()  sleep()  join()  yield()  wait() 等方法

    死亡狀態(tài)--- stop()方法(已過時(shí)) /或run()方法運(yùn)行結(jié)束

1.一個(gè)正在執(zhí)行的線程可能被人為地中斷,讓出CPU的使用權(quán),暫時(shí)中止自己的執(zhí)行,進(jìn)入 阻塞 狀態(tài)。
解析:人為的中斷正在執(zhí)行的線程---- 執(zhí)行wait() 、interrupt() 、sleep()方法等

1.在Java中編寫實(shí)現(xiàn)多線程應(yīng)用有兩種途徑:一種是繼承Thread類創(chuàng)建線程,另一種是實(shí)現(xiàn) Runnable 接口創(chuàng)建線程。
解析: 繼承Thread類來創(chuàng)建線程,不能實(shí)現(xiàn)資源的共享,除非資源使用static修飾。

   實(shí)現(xiàn)Runnable接口創(chuàng)建線程,此時(shí)還需要借助Thread類,因?yàn)镽unnable接口

   沒有start()方法,同時(shí)Thread類是Runnable接口的子類….

1.在線程控制中,可以調(diào)用_____join()____方法,阻塞當(dāng)前正在執(zhí)行的線程,等插隊(duì)線程執(zhí)行完后后再執(zhí)行阻塞線程。
2.多線程訪問某個(gè)共享資源可能出現(xiàn)線程安全問題,此時(shí)可以使用______synchronized_____關(guān)鍵字來實(shí)現(xiàn)線程同步,從而避免安全問題出現(xiàn),但會(huì)影響性能,甚至出現(xiàn)死鎖。

  1. 在線程通信中,調(diào)用wait( )可以是當(dāng)前線程處于等待狀態(tài),而為了喚醒一個(gè)等待的線程,需要調(diào)用的方法是____notify()/notifyAll()__________。
    解析:線程等待使用wait()方法,此方法最先是存在于Object類,Thread類繼承Object類,可以獲取此方法,同時(shí)notify()方法和notifyAll()方法---線程喚醒,最先也是存在于

Object類當(dāng)中。

1.在線程通信中,可以調(diào)用wait()、notify()、notifyAll()三個(gè)方法實(shí)現(xiàn)線程通信,這三個(gè)方法都是____Object____類提供的public方法,所以任何類都具有這三個(gè)方法。

二、 選擇題

下列關(guān)于Java線程的說法正確的是( A )。(選擇一項(xiàng))

A

每一個(gè)Java線程可以看成由代碼、一個(gè)真實(shí)的CPU以及數(shù)據(jù)三部分組成

B.

創(chuàng)建線程的兩種方法中,從Thread類中繼承方式可以防止出現(xiàn)多父類的問題

C.

Thread類屬于java.util程序包

D.

使用new Thread(new X()).run();方法啟動(dòng)一個(gè)線程

解析:

 A、語句正確。

 B、創(chuàng)建線程兩種方法:一是繼承Thread類,一是實(shí)現(xiàn)Runnable接口

    根據(jù)Java語言類的單繼承特性,防止出現(xiàn)多繼承,但是可以實(shí)現(xiàn)多

    重繼承,也可以出現(xiàn)多父類。

C、Thread類是存在于java.lang包下

 D、啟動(dòng)一個(gè)線程是調(diào)用start()方法,之后JVM會(huì)默認(rèn)的調(diào)用run()方法

    run()方法是線程的主體,核心代碼放到此方法當(dāng)中。

以下選項(xiàng)中可以填寫到橫線處,讓代碼正確編譯和運(yùn)行的是( AD )。(選擇一項(xiàng))

public class Test implements Runnable {

     public static void main(String[] args) {

               ___________________________________

               t.start();

               System.out.println("main");

     }

     public void run() {

               System.out.println("thread1!");

     }

}

A.

Thread t = new Thread(new Test());

B.

Test t = new Test();

C.

Thread t = new Test();

D.

Thread t = new Thread();

解析:

線程的創(chuàng)建有兩種方式,其中之一就是實(shí)現(xiàn)Runnable接口。

此接口只有一個(gè)抽象方法---run()方法,啟動(dòng)線程又需要start()方法

此時(shí)還需要借助Thread類,根據(jù)Thread類的構(gòu)造方法:

Public Thread(Runnable run)

需要傳入Runnable接口對象

此題還有一個(gè)方法: 直接創(chuàng)建Thread類對象,調(diào)用start()方法

所以D選項(xiàng)也是正確的,但是此題重點(diǎn)還是考的子類實(shí)現(xiàn)Runnable接口

根據(jù)Thread類的構(gòu)造方法啟動(dòng)線程。

如下代碼創(chuàng)建一個(gè)新線程并啟動(dòng)線程,問:四個(gè)選項(xiàng)中可以保證正確代碼創(chuàng)建target對象,并能編譯正確的是( C )?(選擇一項(xiàng))

public static void main(String[] args) {

      Runnable target=new MyRunnable( ); 

      Thread myThread=new Thread(target);

}

A

public class MyRunnable extends Runnable {

     public void run( ) {        }

}

B.

public class MyRunnable extends Runnable {

     void run( ) {  }

}

C.

public class MyRunnable implements Runnable {

     public void run( ) {        }

}

D.

public class MyRunnable implements Runnable {

     void run( ) { }

解析:接口是用來實(shí)現(xiàn)的,不是繼承,所以AB兩個(gè)選項(xiàng)錯(cuò)誤。

  根據(jù)Java多態(tài)機(jī)制,子類可以為父類(接口)實(shí)例化對象

  根據(jù)子類實(shí)現(xiàn)接口的規(guī)則,子類必須重寫接口當(dāng)中的抽象方法

  此時(shí)又復(fù)習(xí)到了方法重寫的規(guī)則:子類重寫的方法它的權(quán)限必須

  大于等于父類方法權(quán)限(除去private外)。根據(jù)以上得出C是對的

當(dāng)線程調(diào)用start( )后,其所處狀態(tài)為( C )。(選擇一項(xiàng))

A

阻塞狀態(tài)

B.

運(yùn)行狀態(tài)

C.

就緒狀態(tài)

D.

新建狀態(tài)

解析:線程的五個(gè)狀態(tài)也就是它的生命周期:

新建狀態(tài)----通過new關(guān)鍵字來創(chuàng)建線程對象

就緒狀態(tài)----調(diào)用start()方法

運(yùn)行狀態(tài)----調(diào)用run()方法

阻塞狀態(tài)----調(diào)用sleep()、wait()、join() 、yield()、interrupt ()等方法

消亡狀態(tài)----調(diào)用stop()方法,但是此方法已經(jīng)過時(shí)。

下列關(guān)于Thread類提供的線程控制方法的說法中,錯(cuò)誤的是( C )。(選擇一項(xiàng))

A

線程A中執(zhí)行線程B的join()方法,則線程A等待直到B執(zhí)行完成

B.

線程A通過調(diào)用interrupt()方法來中斷其阻塞狀態(tài)

C.

若線程A調(diào)用方法isAlive()返回值為false,則說明A正在執(zhí)行中,也可能是可運(yùn)行狀態(tài)

D.

currentThread()方法返回當(dāng)前線程的引用

解析:

A: join()方法—強(qiáng)制加入,加入的線程執(zhí)行完畢之后才能執(zhí)行其他線程

B:interrupt()方法---線程中斷,題中的說法有些牽強(qiáng)

C:isAlive()方法---判斷一個(gè)線程是否在活動(dòng),如果在活動(dòng)返回真,反之假

D:currentThread()方法返回正在執(zhí)行的線程

從以上得知,C明顯錯(cuò)誤。

下列關(guān)于線程的優(yōu)先級說法中,正確的是( BD )。(選擇兩項(xiàng))

A

線程的優(yōu)先級是不能改變的

B.

線程的優(yōu)先級是在創(chuàng)建線程時(shí)設(shè)置的

C.

在創(chuàng)建線程后的任何時(shí)候都可以重新設(shè)置

D.

線程的優(yōu)先級的范圍在1-10之間

   解析:線程的優(yōu)先級可以通過setPriority(int newPriority)的方法進(jìn)行設(shè)置

         線程一共有三個(gè)優(yōu)先級,分別是:最低優(yōu)先級(1) 中等優(yōu)先級(5)

         最高優(yōu)先級(10),咱們經(jīng)常寫的main方法就是中等優(yōu)先級線程。

         A:線程的優(yōu)先級是可以更改也可以獲取,但是有一點(diǎn),即使設(shè)置為最高

            優(yōu)先級也不一定先執(zhí)行,只是它優(yōu)先執(zhí)行的幾率比較高。

         B:線程的優(yōu)先級是在創(chuàng)建時(shí)進(jìn)行設(shè)置,通過setPriority()方法設(shè)置

       C:正在執(zhí)行的線程是不允許重新設(shè)置線程優(yōu)先級的。

D:線程的優(yōu)先級范圍是1—10 符合要求

以下選項(xiàng)中關(guān)于Java中線程控制方法的說法正確的是( AD )。(選擇二項(xiàng))

A.

join ( ) 的作用是阻塞指定線程等到另一個(gè)線程完成以后再繼續(xù)執(zhí)行

B.

sleep ( ) 的作用是讓當(dāng)前正在執(zhí)行線程暫停,線程將轉(zhuǎn)入就緒狀態(tài)

C.

yield ( ) 的作用是使線程停止運(yùn)行一段時(shí)間,將處于阻塞狀態(tài)

D.

setDaemon( )的作用是將指定的線程設(shè)置成后臺(tái)線程

解析:

A:join()方法—線程的強(qiáng)制加入,加入的線程執(zhí)行完畢之后再執(zhí)行其他線程

B:sleep()方法—線程休眠,等時(shí)間過時(shí),線程處于運(yùn)行狀態(tài)

C:yield()方法—線程禮讓,讓出CUP資源,其他線程先執(zhí)行,有些與join()

            方法類似

D:setDaemon()方法--將指定的線程設(shè)置成后臺(tái)線程,對的。

題的答案是:AD,但是個(gè)人感覺C選項(xiàng)也是對的……

在多個(gè)線程訪問同一個(gè)資源時(shí),可以使用( A )關(guān)鍵字來實(shí)現(xiàn)線程同步,保證對資源安全訪問。(選擇一項(xiàng))

A.

Synchronized

B.

Transient

C.

Static

D.

Yield

     解析:關(guān)于同步,有兩種實(shí)現(xiàn)方式,一種是同步方法,一種是同步代碼塊

            無論怎樣,都需要使用到synchronized關(guān)鍵字。

            同步方法:

                 權(quán)限修飾符  synchronized  返回值類型  方法名稱(參數(shù)列表){

                 N行代碼;

}

        同步代碼塊:

             Synchronized(對象){

                 N行代碼;

}

Java中線程安全問題是通過關(guān)鍵字( C )解決的?。(選擇一項(xiàng))

A.

Finally

B.

wait( )

C.

Synchronized

D.

notify( )

以下說法中關(guān)于線程通信的說法錯(cuò)誤的是( D )?。(選擇一項(xiàng))

A.

可以調(diào)用wait()、notify()、notifyAll()三個(gè)方法實(shí)現(xiàn)線程通信

B.

wait()、notify()、notifyAll()必須在synchronized方法或者代碼塊中使用
C.

wait()有多個(gè)重載的方法,可以指定等待的時(shí)間

D.

wait()、notify()、notifyAll()是Object類提供的方法,子類可以重寫

解析:

A選項(xiàng):

在線程通信中,可以調(diào)用wait()、notify()、notifyAll()三個(gè)方法實(shí)現(xiàn)線程通信,這三個(gè)方法都是Object類提供的public方法,所以任何類都具有這三個(gè)方法。

B選項(xiàng):在編程題的第二題當(dāng)中,wait()方法、notify()方法、notifyAll()方法都是寫在同步方法當(dāng)中,具體可以查看此類的源碼。

C選項(xiàng):Object類當(dāng)中的wait方法的重載如下:

public final void wait()

public final void wait(long timeout)
public final void wait(long timeout, int nanos)
三個(gè)方法都拋出異常-- InterruptedException
D選項(xiàng) : 看A選項(xiàng)的解釋
以上三個(gè)方法都使用final修飾,所以子類是不能重寫的

三、 判斷題

1.進(jìn)程是線程Thread內(nèi)部的一個(gè)執(zhí)行單元,它是程序中一個(gè)單一順序控制流程。( × )
解析:線程是進(jìn)程的一個(gè)執(zhí)行單位,進(jìn)程包含線程。

1.Thread類實(shí)現(xiàn)了Runnable接口。( √ )
解析:Thread類在JDK當(dāng)中的定義如下:

     Public class Thread extends Object  implements Runnable

    從定義可知,它是Runnable接口的子類。

1.一個(gè)進(jìn)程可以包括多個(gè)線程。兩者的一個(gè)主要區(qū)別是:線程是資源分配的單位,而進(jìn)程CPU調(diào)度和執(zhí)行的單位。( × )
解析:不管是進(jìn)程還是線程,都是通過循環(huán)獲得自己執(zhí)行的時(shí)間片,獲得CUP資源。

1.用new關(guān)鍵字建立一個(gè)線程對象后,該線程對象就處于新生狀態(tài)。處于新生狀態(tài)的線程有自己的內(nèi)存空間,通過調(diào)用start進(jìn)入就緒狀態(tài)。( √ )
解析:具體解析看選擇題第四題的解釋。

1.A線程的優(yōu)先級是10,B線程的優(yōu)先級是1,那么當(dāng)進(jìn)行調(diào)度時(shí)一定會(huì)先調(diào)用A( × )
解析:線程的執(zhí)行,不是誰的優(yōu)先級高就先執(zhí)行,只是它的概率會(huì)高。

1.線程可以用yield使低優(yōu)先級的線程運(yùn)行。( × )
解析:yield()方法是線程禮讓,可以讓出自己執(zhí)行其他線程,由于線程的執(zhí)行存在嚴(yán)重

 的隨機(jī)性,不能確定使低優(yōu)先級的線程執(zhí)行。

1.Thread.sleep( )方法調(diào)用后,當(dāng)?shù)却龝r(shí)間未到,該線程所處狀態(tài)為阻塞狀態(tài)。當(dāng)?shù)却龝r(shí)間已到,該線程所處狀態(tài)為運(yùn)行狀態(tài)。( √ )
解析:sleep()方法是線程休眠,處于阻塞狀態(tài),當(dāng)時(shí)間一到,就會(huì)執(zhí)行處于運(yùn)行狀態(tài)。

  如果真要追究用詞的嚴(yán)謹(jǐn)性,應(yīng)該不是”等待時(shí)間”,而是”休眠時(shí)間”。

1.當(dāng)一個(gè)線程進(jìn)入一個(gè)對象的一個(gè)synchronized方法后,其它線程不可以再進(jìn)入該對象同步的其它方法執(zhí)行。( √ )
解析:對的,可以查看一下編程題第二題的源碼。

1.wait方法被調(diào)用時(shí),所在線程是會(huì)釋放所持有的鎖資源, sleep方法不會(huì)釋放。( √ )
解析:sleep 是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時(shí)間,給執(zhí)行機(jī)會(huì)給其他線程,但是監(jiān)控狀態(tài)依然保持,到時(shí)后會(huì)自動(dòng)恢復(fù),所以調(diào)用sleep 不會(huì)釋放對象鎖。
wait 是Object 類的方法,對此對象調(diào)用wait 方法導(dǎo)致本線程放棄對象鎖,進(jìn)入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify 方法(或notifyAll)后本線程才進(jìn)入對象鎖定池準(zhǔn)備獲得對象鎖進(jìn)入運(yùn)行狀態(tài)。

1.wait、notify、notifyAll是在Object類中定義的方法。( √ )
解析:具體可以查看API幫助文檔,查看。

1.notify是喚醒所在對象wait pool中的第一個(gè)線程。( × )
解析:喚醒的不一定是第一個(gè)線程。

  JDK已經(jīng)明確說明喚醒哪個(gè)thread是隨意決定的,沒有特定順序 

The choice is arbitrary and occurs at the discretion of the implementation

四、 簡答題

1.簡述程序、進(jìn)程和線程的聯(lián)系和區(qū)別。
2.創(chuàng)建線程的兩種方式分別是什么?各有什么優(yōu)缺點(diǎn)。
3.sleep、yield、join方法的區(qū)別?
4.synchronize修飾的語句塊,如下面的代碼。是表示該代碼塊運(yùn)行時(shí)必須獲得account對象的鎖。如果沒有獲得,會(huì)有什么情況發(fā)生?
synchronized (account) {

     if(account.money-drawingNum<0){

               return;

     }

}

1.請你簡述sleep( )和wait( )有什么區(qū)別?
2.死鎖是怎么造成的?用文字表達(dá)。再寫一個(gè)代碼示例。
3.Java中實(shí)現(xiàn)線程通信的三個(gè)方法及其作用。
4.為什么不推薦使用stop和destroy方法來結(jié)束線程的運(yùn)行?

五、 編碼題

1.設(shè)計(jì)一個(gè)多線程的程序如下:設(shè)計(jì)一個(gè)火車售票模擬程序。假如火車站要有100張火車票要賣出,現(xiàn)在有5個(gè)售票點(diǎn)同時(shí)售票,用5個(gè)線程模擬這5個(gè)售票點(diǎn)的售票情況。

public class CharPrint extends Thread
{
    // 定義屬性
    private Printer p;
    //構(gòu)造方法
    public CharPrint(Printer p)
    {
        super();
        this.p = p;
    }
    //重寫run()方法
    public void run()
    {
        char c = 'A';//定義起始位置
        //通過for循環(huán)對其進(jìn)行輸出
        while (c <= 'Z')
        {
            p.print(c);
            c++;//控制while循環(huán)當(dāng)中的條件表達(dá)式
        }
    }
}
public class NumberPrint extends Thread
{
    //定義屬性
    private Printer p;
    //構(gòu)造方法
    public NumberPrint(Printer p)
    {
        this.p = p;
    }
    //重寫run()方法
    public void run()
    {
        int i = 1;//定義起始位置
        while (i <= 52)
        {
            p.print(i);
            i++;//控制while循環(huán)當(dāng)中的條件表達(dá)式
        }
    }
}
public class Printer
{
    //定義一個(gè)int類型變量---用于計(jì)數(shù)
    int index = 1;
    //同步的方法---print()
    public synchronized void print(int i)
    {
        //判斷是否是3的倍數(shù)
        while (index % 3 == 0)
        {
            try
            {
                wait();//線程等待
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //打印輸出數(shù)字
        System.out.print("" + i);
        //控制while循環(huán)中的條件表達(dá)式
        index++;
        //線程喚醒
        notifyAll();
    }
    public synchronized void print(char c)
    {
        //判斷是否是3的倍數(shù)
        while (index % 3 != 0)
        {
            try
            {
                wait();
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        //打印字母
        System.out.print("" + c);
        //控制while循環(huán)中的條件表達(dá)式
        index++;
        //喚醒線程
        notifyAll();
    }
}
public class Test
{
    public static void main(String[] args)
    {
        //創(chuàng)建Printer對象,為NumberPrint()類構(gòu)造方法做準(zhǔn)備
        Printer p = new Printer();
        //創(chuàng)建線程---子類為父類實(shí)例化對象
        Thread t1 = new NumberPrint(p);
        Thread t2 = new CharPrint(p);
        //啟動(dòng)線程
        t1.start();
        t2.start();
    }
}

2.編寫兩個(gè)線程,一個(gè)線程打印1-52的整數(shù),另一個(gè)線程打印字母A-Z。打印順序?yàn)?2A34B56C….5152Z。即按照整數(shù)和字母的順序從小到大打印,并且每打印兩個(gè)整數(shù)后,打印一個(gè)字母,交替循環(huán)打印,直到打印到整數(shù)52和字母Z結(jié)束。
要求:

  1.     編寫打印類Printer,聲明私有屬性index,初始值為1,用來表示是第幾次打印。
    
  2.     在打印類Printer中編寫打印數(shù)字的方法print(int i),3的倍數(shù)就使用wait()方法等待,否則就輸出i,使用notifyAll()進(jìn)行喚醒其它線程。
    
  3.     在打印類Printer中編寫打印字母的方法print(char c),不是3的倍數(shù)就等待,否則就打印輸出字母c,使用notifyAll()進(jìn)行喚醒其它線程。
    
  4.     編寫打印數(shù)字的線程N(yùn)umberPrinter繼承Thread類,聲明私有屬性private Printer p;在構(gòu)造方法中進(jìn)行賦值,實(shí)現(xiàn)父類的run方法,調(diào)用Printer類中的輸出數(shù)字的方法。
    
  5.     編寫打印字母的線程LetterPrinter繼承Thread類,聲明私有屬性private Printer p;在構(gòu)造方法中進(jìn)行賦值,實(shí)現(xiàn)父類的run方法,調(diào)用Printer類中的輸出字母的方法。
    
  6.     編寫測試類Test,創(chuàng)建打印類對象,創(chuàng)建兩個(gè)線程類對象,啟動(dòng)線程。
    
public class TicketSalSystem implements Runnable
{
    // 定義變量---票數(shù)/票號
    public int ticket = 100;
    public int count = 0;
    // 重寫run()方法
    public void run()
    {
        // 定義while循環(huán), 循環(huán)售票
        while (ticket > 0)
        {
            // 根據(jù)題的要求,實(shí)現(xiàn)同步,此時(shí)定義同步代碼塊
            synchronized (this)
            {// 傳入對象,使用this代替當(dāng)前類對象
                // 判斷是否還有票,如果大于零說明還有票可賣
                if (ticket > 0)
                {
                    // 線程休眠0.5秒
                    try
                    {
                        Thread.sleep(500);
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    count++; // 票號++
                    ticket--;// 循環(huán)售票,賣一張少一張
                    // 輸出當(dāng)前的售票窗口和票號
                    System.out.println(Thread.currentThread().getName()
                            + "\t當(dāng)前票號:" + count);
                }
            }
        }
    }
}
public class TicketTest
{
    public static void main(String[] args)
    {
        // 創(chuàng)建線程類對象
        TicketSalSystem st = new TicketSalSystem();
        // 啟動(dòng)5次線程
        for (char i = 'A'; i <= 'F'; i++)
        {
            /*
                             * 創(chuàng)建匿名Thread類對象
                             *    1、根據(jù)Thread類構(gòu)造方法,傳入Runnable接口對象
                             *       TicketSalSystem類是Runnable接口的子類,子類對象st可以讓父類接收
                             *    2、Thread類的構(gòu)造方法如下:
                             *       public Thread(Runnable run,String name)
                             *       在創(chuàng)建線程的同時(shí),為線程名稱
                             *    3、啟動(dòng)線程是使用start方法,啟動(dòng)之后JVM會(huì)默認(rèn)的區(qū)調(diào)用run()方法
             */
            new Thread(st, "售票口" + i).start();
        }
    }
}

六、 可選題

1.設(shè)計(jì)4個(gè)線程,其中兩個(gè)線程每次對j增加1,另外兩個(gè)線程對j每次減少1。

要求:使用內(nèi)部類實(shí)現(xiàn)線程,對j增減的時(shí)候不考慮順序問題。

public class ThreadTest61
{
    //聲明成員變量j
    private int j;
    public static void main(String[] args)
    {
        //創(chuàng)建ThreadTest61的對象
        ThreadTest61 tt = new ThreadTest61();
        //創(chuàng)建內(nèi)部線程類對象
        Inc inc = tt.new Inc();
        Dec dec = tt.new Dec();
        for (int i = 0; i < 2; i++)
        {
            // 創(chuàng)建線程對象,啟動(dòng)線程
            Thread t = new Thread(inc);
            t.start();
            // 創(chuàng)建線程對象,啟動(dòng)線程
            t = new Thread(dec);
            t.start();
        }
    }
    //實(shí)現(xiàn)同步對j的值加
    private synchronized void inc()
    {
        //調(diào)用此方法一次,對j就增加一次
        j++;
        System.out.println(Thread.currentThread().getName() + "-inc:" + j);
    }
    //實(shí)現(xiàn)同步對j的值減
    private synchronized void dec()
    {
        //調(diào)用此方法一次,對j就減一次
        j--;
        System.out.println(Thread.currentThread().getName() + "-dec:" + j);
    }
    //內(nèi)部類實(shí)現(xiàn)Runnable接口,重寫run()方法
    class Inc implements Runnable
    {
        public void run()
        {
            //for循環(huán)當(dāng)中調(diào)用inc()方法,實(shí)現(xiàn)每次對j加1
            for (int i = 0; i < 100; i++)
            {
                //調(diào)用加的方法
                inc();
            }
        }
    }
    //內(nèi)部類實(shí)現(xiàn)Runnable接口,重寫run()方法
    class Dec implements Runnable
    {
        public void run()
        {
            //for循環(huán)當(dāng)中調(diào)用inc()方法,實(shí)現(xiàn)每次對j減1
            for (int i = 0; i < 100; i++)
            {
                //調(diào)用減的方法
                dec();
            }
        }
    }
}

2.編寫多線程程序,模擬多個(gè)人通過一個(gè)山洞的模擬。這個(gè)山洞每次只能通過一個(gè)人,每個(gè)人通過山洞的時(shí)間為5秒,有10個(gè)人同時(shí)準(zhǔn)備過此山洞,顯示每次通過山洞人的姓名和順序。

public class ThreadTest62
{
    public static void main(String[] args)
    {
        /*創(chuàng)建一個(gè)山洞對象,為Thread類構(gòu)造方法做準(zhǔn)備
                  *    public Thread(Runnable run,String name)
         */
        Tunnel tul = new Tunnel();
        //創(chuàng)建十個(gè)過山洞線程,并為線程命名
        Thread p1 = new Thread(tul, "p1");
        Thread p2 = new Thread(tul, "p2");
        Thread p3 = new Thread(tul, "p3");
        Thread p4 = new Thread(tul, "p4");
        Thread p5 = new Thread(tul, "p5");
        Thread p6 = new Thread(tul, "p6");
        Thread p7 = new Thread(tul, "p7");
        Thread p8 = new Thread(tul, "p8");
        Thread p9 = new Thread(tul, "p9");
        Thread p10 = new Thread(tul, "p10");
        //啟動(dòng)十個(gè)線程
        p1.start();
        p2.start();
        p3.start();
        p4.start();
        p5.start();
        p6.start();
        p7.start();
        p8.start();
        p9.start();
        p10.start();
    }
}
//創(chuàng)建山洞類并實(shí)現(xiàn)Runnable接口,重寫run()方法
class Tunnel implements Runnable
{
    //定義變量,初始化過山洞人數(shù)
    int crossedNum = 0;
    //重寫run()方法,在此方法當(dāng)中調(diào)用cross()方法
    public void run()
    {
        cross();
    }
    //定義過山洞的同步方法
    public synchronized void cross()
    {
        //每個(gè)人通過山洞的時(shí)間為5秒
        try
        {
            Thread.sleep(5000);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        //人數(shù)統(tǒng)計(jì),過一個(gè)人增加一個(gè)人
        crossedNum++;
        //顯示每次通過山洞人的姓名
        System.out.println(Thread.currentThread().getName()
                + "通過了山洞,這是第" + crossedNum + "個(gè)用戶");
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容