Java多線程

學(xué)習(xí)java多線程的一下知識(shí)的總結(jié),寫在這里,防止自己遺忘,也是為了復(fù)習(xí)。

JVM的啟動(dòng)是單線程還是多線程的??

JVM啟動(dòng)的時(shí)候不僅僅啟動(dòng)了主線程,而且啟動(dòng)了垃圾回收線程,所以JVM的啟動(dòng)是多線程的。

如何實(shí)現(xiàn)多線程?

兩種方式:

  1. 繼承Thread類
    1. 自定義MyThread類繼承了Thread類
    2. 重寫MyThread類中的run()方法
    3. 創(chuàng)建MyThread對(duì)象
    4. 啟動(dòng)線程對(duì)象
  1. 實(shí)現(xiàn)Runable接口
    1. 自定義MyRunnable類實(shí)現(xiàn)了Runnable接口
    2. 重寫MyRunnable類中的run()方法
    3. 創(chuàng)建MyRunnable對(duì)象
    4. 創(chuàng)建Thread對(duì)象,把MyRunnable對(duì)象對(duì)象作為構(gòu)造函數(shù)的入?yún)?/li>

對(duì)于繼承Thread來說,是通過重寫了run方法來實(shí)現(xiàn)的,因?yàn)橐粋€(gè)類的代碼并不是都需要多線程執(zhí)行的,只會(huì)執(zhí)行run方法里面的代碼。

為什么有兩張方式來實(shí)現(xiàn)多線程???

  1. 由于Java只支持單繼承,避免單繼承導(dǎo)致的多線程的局限性
  2. 適合多個(gè)相同程序的代碼去處理同一個(gè)資源,吧線程相同程序的代碼,數(shù)據(jù)有效分離,體現(xiàn)了Java面向?qū)ο蟮脑O(shè)計(jì)思想。

如果重復(fù)調(diào)用run會(huì)發(fā)現(xiàn),還是單線程執(zhí)行,原因是run方法它是單行程的。

可以通過start方法來執(zhí)行,如果調(diào)用兩次start方法,并不能進(jìn)行多線程操作,由于已經(jīng)執(zhí)行了start方法,再次執(zhí)行start會(huì)報(bào)錯(cuò),,報(bào)錯(cuò)信息如下:

連續(xù)執(zhí)行對(duì)象的線程start方法報(bào)錯(cuò).png

所以可以實(shí)例化兩個(gè)對(duì)象,分別啟動(dòng)對(duì)象的線程,會(huì)發(fā)現(xiàn)他們兩個(gè)確實(shí)是多線程執(zhí)行的。看到兩個(gè)for循環(huán)是同時(shí)執(zhí)行的,并沒有順序執(zhí)行。

代碼示例:

package com.aircjm.thread;

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
        }
    }
}

package com.aircjm.thread;

public class ThreadTest {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();

        //由于run()方法時(shí)單線程的,所以還是按照單線程執(zhí)行,一個(gè)run()執(zhí)行完了,另一個(gè)run()才會(huì)執(zhí)行
        //myThread.run();
        //myThread.run();

        //可以通過start()方法來啟動(dòng)線程
        //兩者之間的區(qū)別,start是使該線程開始執(zhí)行,JVM調(diào)用該線程的run()方法
        //myThread.start();
        //myThread.start();

        MyThread myThread1 = new MyThread();
        MyThread myThread2 = new MyThread();

        myThread1.start();
        myThread2.start();


    }
}

如何獲取繼承Thread的線程對(duì)象的名稱

public final String getName() //獲取線程的名詞

線程控制的幾個(gè)方法:

休眠線程:
public static void sleep(long millis) throws InterruptedException

在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),此操作受到系統(tǒng)計(jì)時(shí)器和調(diào)度程序精度和準(zhǔn)確性的影響。該線程不丟失任何監(jiān)視器的所屬權(quán)。
啟動(dòng)線程:
start

public void start()
使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。
結(jié)果是兩個(gè)線程并發(fā)地運(yùn)行;當(dāng)前線程(從調(diào)用返回給 start 方法)和另一個(gè)線程(執(zhí)行其 run 方法)。

多次啟動(dòng)一個(gè)線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動(dòng)。

拋出:
IllegalThreadStateException - 如果線程已經(jīng)啟動(dòng)。
另請(qǐng)參見:
run(), stop()
run

public void run()
如果該線程是使用獨(dú)立的 Runnable 運(yùn)行對(duì)象構(gòu)造的,則調(diào)用該 Runnable 對(duì)象的 run 方法;否則,該方法不執(zhí)行任何操作并返回。
Thread 的子類應(yīng)該重寫該方法。

加入線程:

禮讓線程:

守護(hù)線程:

中斷線程:

啟動(dòng)線程用的是哪個(gè)方法?

start()

run()和start()方法的區(qū)別?

  1. run直接調(diào)用,調(diào)用的是普通方法
  2. start()方法,是啟動(dòng)線程,然后JVM調(diào)用了run()方法

如何讓線程安全??

給需要線程安全的地方進(jìn)行加鎖

public class SellTicket implements Runnable {
    private Integer ticketNum = 100;
    public void run() {
        while (true){
            synchronized (ticketNum){
                if (ticketNum>0){
                    System.out.println("now is sell "+ ticketNum-- +" ticket");
                }
            }
        }
    }
}

加鎖的方式有多種,可以給代碼塊加鎖(鎖對(duì)象是任意對(duì)象),可以給方法加鎖(鎖對(duì)象是this),也可以給靜態(tài)方法加鎖(鎖對(duì)象是字節(jié)碼文件)

學(xué)習(xí)到的線程安全的對(duì)象有:

StringBuffer stringBuffer = new StringBuffer();
Vector<String> vector = new Vector<String>();
Hashtable<String, Object> hashTable = new Hashtable<String, Object>();
// 即使線程安全但是也不推薦使用
Vector<String> vector = new Vector<String>();
Hashtable<String, Object> hashTable = new Hashtable<String, Object>();

// 如何使用線程安全的List呢??
List<String> list = Collections.synchronizedList(new ArrayList<String>()); // 線程安全
List<String> list1 = new ArrayList<String>(); //線程不安全

通過靜態(tài)方法獲取到線程安全的List集合

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 概述 這篇文章中,我不會(huì)說多線程是什么、線程和進(jìn)程的區(qū)別、多線程有什么用,當(dāng)然我也不會(huì)說什么是串行、什么是并行等問...
    hashakey閱讀 310評(píng)論 0 0
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,767評(píng)論 0 9
  • Java Thread 總結(jié) 【顯示目錄】 ?線程的概述(Introduction) 線程是一個(gè)程序的多個(gè)執(zhí)行路徑...
    夏6閱讀 355評(píng)論 0 0
  • 1.要做一個(gè)盡可能流暢的ListView,你平時(shí)在工作中如何進(jìn)行優(yōu)化的? ①Item布局,層級(jí)越少越好,使用hie...
    fozero閱讀 756評(píng)論 0 0