国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

什么是Java多線程?

高璐 / 1179人閱讀

摘要:是不能直接調(diào)用系統(tǒng)功能的,所以,我們沒有辦法直接實(shí)現(xiàn)多線程程序。通過查看,我們知道了有種方式實(shí)現(xiàn)多線程程序。使用的是搶占式調(diào)度模型演示如何設(shè)置和獲取線程優(yōu)先級返回線程對象的優(yōu)先級更改線程的優(yōu)先級線程默認(rèn)優(yōu)先級是。線程優(yōu)先級的范圍是。

第五階段 多線程 前言:
一個(gè)場景:周末,帶著并不存在的女票去看電影,無論是現(xiàn)場買票也好,又或是手機(jī)買票也好,上一秒還有位置,遲鈍了一下以后,就顯示該座位已經(jīng)無法選中,一不留神就沒有座位了,影院的票是一定的,但是究竟是如何做到,多個(gè)窗口或者用戶同時(shí)出票而又不重復(fù)的呢? 這就是我們今天所要講解的多線程問題
(一) 線程和進(jìn)程的概述 (1) 進(jìn)程

進(jìn)程:進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)用的獨(dú)立單位。每一個(gè)進(jìn)程都有它自己的內(nèi)存空間和系統(tǒng)資源

多線程:在同一個(gè)時(shí)間段內(nèi)可以執(zhí)行多個(gè)任務(wù),提高了CPU的使用率

(2) 線程

線程:進(jìn)程的執(zhí)行單元,執(zhí)行路徑

單線程:一個(gè)應(yīng)用程序只有一條執(zhí)行路徑

多線程:一個(gè)應(yīng)用程序有多條執(zhí)行路徑

多進(jìn)程的意義?—— 提高CPU的使用率

多線程的意義? —— 提高應(yīng)用程序的使用率

(3) 補(bǔ)充

并行和并發(fā)

并行是物理上同時(shí)發(fā)生,指在某一個(gè)時(shí)間點(diǎn)同時(shí)運(yùn)行多個(gè)程序

并發(fā)是邏輯上同時(shí)發(fā)生,指在某一個(gè)時(shí)間段內(nèi)同時(shí)運(yùn)行多個(gè)程序

Java程序運(yùn)行原理和JVM的啟動(dòng)是否是多線程的 ?

Java程序的運(yùn)行原理:

由java命令啟動(dòng)JVM,JVM啟動(dòng)就相當(dāng)于啟動(dòng)了一個(gè)進(jìn)程

接著有該進(jìn)程創(chuàng)建了一個(gè)主線程去調(diào)用main方法

JVM虛擬機(jī)的啟動(dòng)是單線程的還是多線程的 ?

垃圾回收線程也要先啟動(dòng),否則很容易會出現(xiàn)內(nèi)存溢出

現(xiàn)在的垃圾回收線程加上前面的主線程,最低啟動(dòng)了兩個(gè)線程,所以,jvm的啟動(dòng)其實(shí)是多線程的

JVM啟動(dòng)至少啟動(dòng)了垃圾回收線程和主線程,所以是多線程的

(二) 多線程代碼實(shí)現(xiàn)

需求:我們要實(shí)現(xiàn)多線程的程序。

如何實(shí)現(xiàn)呢?

由于線程是依賴進(jìn)程而存在的,所以我們應(yīng)該先創(chuàng)建一個(gè)進(jìn)程出來。

而進(jìn)程是由系統(tǒng)創(chuàng)建的,所以我們應(yīng)該去調(diào)用系統(tǒng)功能創(chuàng)建一個(gè)進(jìn)程。

Java是不能直接調(diào)用系統(tǒng)功能的,所以,我們沒有辦法直接實(shí)現(xiàn)多線程程序。

但是呢?Java可以去調(diào)用C/C++寫好的程序來實(shí)現(xiàn)多線程程序。

由C/C++去調(diào)用系統(tǒng)功能創(chuàng)建進(jìn)程,然后由Java去調(diào)用這樣的東西,

然后提供一些類供我們使用。我們就可以實(shí)現(xiàn)多線程程序了。

通過查看API,我們知道了有2種方式實(shí)現(xiàn)多線程程序。

方式1:繼承Thread類

步驟:

自定義MyThread(自定義類名)繼承Thread類

MyThread類中重寫run()

創(chuàng)建對象

啟動(dòng)線程

public class MyThread extends Thread{
    public MyThread() {
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            System.out.println(getName() + ":" + i);
        }
    }
}
public class MyThreadTest {
    public static void main(String[] args) {
        //創(chuàng)建線程對象
        MyThread my = new MyThread();
        //啟動(dòng)線程,run()相當(dāng)于普通方法的調(diào)用,單線程效果
        //my.run();
        //首先啟動(dòng)了線程,然后再由jvm調(diào)用該線程的run()方法,多線程效果
        my.start();

        //兩個(gè)線程演示,多線程效果需要?jiǎng)?chuàng)建多個(gè)對象而不是一個(gè)對象多次調(diào)用start()方法
        MyThread my1 = new MyThread();
        MyThread my2 = new MyThread();

        my1.start();
        my2.start();
    }
}

//運(yùn)行結(jié)果
Thread-1:0
Thread-1:1
Thread-1:2
Thread-0:0
Thread-1:3
Thread-0:1
Thread-0:2
......
Thread-0:95
Thread-0:96
Thread-0:97
Thread-0:98
Thread-0:99
方式2:實(shí)現(xiàn)Runnable接口 (推薦)

步驟:

自定義類MyuRunnable實(shí)現(xiàn)Runnable接口

重寫run()方法

創(chuàng)建MyRunable類的對象

創(chuàng)建Thread類的對象,并把C步驟的對象作為構(gòu)造參數(shù)傳遞

public class MyRunnable implements Runnable {
    public MyRunnable() {
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 100; i++){
            //由于實(shí)現(xiàn)接口的方式不能直接使用Thread類的方法了,但是可以間接的使用
            System.out.println(Thread.currentThread().getName() + ":" + i);
        }
    }
}
public class MyRunnableTest {
    public static void main(String[] args) {
        //創(chuàng)建MyRunnable類的對象
        MyRunnable my = new MyRunnable();

        //創(chuàng)建Thread類的對象,并把C步驟的對象作為構(gòu)造參數(shù)傳遞
//        Thread t1 = new Thread(my);
//        Thread t2 = new Thread(my);
        //下面具體講解如何設(shè)置線程對象名稱
//        t1.setName("User1");
//        t1.setName("User2");

        Thread t1 = new Thread(my,"User1");
        Thread t2 = new Thread(my,"User2");

        t1.start()
        t2.start();
    }
}

實(shí)現(xiàn)接口方式的好處

可以避免由于Java單繼承帶來的局限性

適合多個(gè)相同程序的代碼去處理同一個(gè)資源的情況,把線程同程序的代碼,數(shù)據(jù)有效分離,較好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想

如何理解------可以避免由于Java單繼承帶來的局限性

比如說,某個(gè)類已經(jīng)有父類了,而這個(gè)類想實(shí)現(xiàn)多線程,但是這個(gè)時(shí)候它已經(jīng)不能直接繼承Thread類了

(接口可以多實(shí)現(xiàn)implements,但是繼承extends只能單繼承) ,它的父類也不想繼承Thread因?yàn)椴恍枰獙?shí)現(xiàn)多線程

(三) 獲取和設(shè)置線程對象
//獲取線程的名稱
public?final?String?getName()

//設(shè)置線程的名稱
public?final?void?setName(String?name)
設(shè)置線程的名稱 (如果不設(shè)置名稱的話,默認(rèn)是Thread-??(編號) )

方法一:無參構(gòu)造 + setXxx (推薦)

//創(chuàng)建MyRunnable類的對象
MyRunnable my = new MyRunnable();

//創(chuàng)建Thread類的對象,并把C步驟的對象作為構(gòu)造參數(shù)傳遞
Thread t1 = new Thread(my);
Thread t2 = new Thread(my);
t1.setName("User1");
t1.setName("User2");
        
//與上面代碼等價(jià)
Thread t1 = new Thread(my,"User1");
Thread t2 = new Thread(my,"User2");

方法二:(稍微麻煩,要手動(dòng)寫MyThread的帶參構(gòu)造方法,方法一不用)

//MyThread類中

public MyThread(String name){
    super(name);//直接調(diào)用父類的就好
}

//MyThreadTest類中
MyThread my = new MyThread("admin");
獲取線程名稱

注意:重寫run方法內(nèi)獲取線程名稱的方式

//Thread
getName()

//Runnable
//由于實(shí)現(xiàn)接口的方式不能直接使用Thread類的方法了,但是可以間接的使用
Thread.currentThread().getName()

使用實(shí)現(xiàn)Runnable接口方法的時(shí)候注意:main方法所在的測試類并不繼承Thread類,因此并不能直接使用getName()方法來獲取名稱。

//這種情況Thread類提供了一個(gè)方法:
//public static Thread currentThread():

//返回當(dāng)前正在執(zhí)行的線程對象,返回值是Thread,而Thread恰巧可以調(diào)用getName()方法
System.out.println(Thread.currentThread().getName());
(四) 線程調(diào)度及獲取和設(shè)置線程優(yōu)先級
假如我們的計(jì)算機(jī)只有一個(gè) CPU,那么 CPU 在某一個(gè)時(shí)刻只能執(zhí)行一條指令,線程只有得到 CPU時(shí)間片,也就是使用權(quán),才可以執(zhí)行指令。那么Java是如何對線程進(jìn)行調(diào)用的呢?

線程有兩種調(diào)度模型:

分時(shí)調(diào)度模型 :所有線程輪流使用 CPU 的使用權(quán),平均分配每個(gè)線程占用 CPU 的時(shí)間片

搶占式調(diào)度模型 :優(yōu)先讓優(yōu)先級高的線程使用 CPU,如果線程的優(yōu)先級相同,那么會隨機(jī)選擇一個(gè),優(yōu)先級高的線程獲取的 CPU 時(shí)間片相對多一些。

Java使用的是搶占式調(diào)度模型

//演示如何設(shè)置和獲取線程優(yōu)先級

//返回線程對象的優(yōu)先級
public final int getPriority()

//更改線程的優(yōu)先級
public final void setPriority(int newPriority)

線程默認(rèn)優(yōu)先級是5。

線程優(yōu)先級的范圍是:1-10。

線程優(yōu)先級高僅僅表示線程獲取的 CPU時(shí)間片的幾率高,但是要在次數(shù)比較多,或者多次運(yùn)行的時(shí)候才能看到比較好的效果。

(五) 線程控制

在后面的案例中會用到一些,這些控制功能不是很難,可以自行測試。

//線程休眠
public static void sleep(long millis)

//線程加入(等待該線程終止,主線程結(jié)束后,其余線程開始搶占資源)
public final void join()

//線程禮讓(暫停當(dāng)前正在執(zhí)行的線程對象,并且執(zhí)行其他線程讓多個(gè)線程的執(zhí)行更加和諧,但是不能保證一人一次)
public static void yield()

//后臺線程(某線程結(jié)束后,其他線程也結(jié)束)
public final void setDaemon(boolean on)

//(過時(shí)了但還可以用)
public final void stop()

//中斷線程
public void interrupt()
(六) 線程的生命周期

新建 —— 創(chuàng)建線程對象

就緒 —— 線程對象已經(jīng)啟動(dòng),但是還沒有獲取到CPU的執(zhí)行權(quán)

運(yùn)行 —— 獲取到了CPU的執(zhí)行權(quán)

阻塞 —— 沒有CPU的執(zhí)權(quán),回到就緒

死亡 —— 代碼運(yùn)行完畢,線程消亡

(七) 多線程電影院出票案例
public class SellTickets implements Runnable {
    private int tickets = 100;

    @Override
    public void run() {
        while (true){
            if (tickets > 0){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() 
                                   + "正在出售第" + (tickets--) + "張票");
            }
        }
    }
}
public class SellTicketsTest {
    public static void main(String[] args) {
        //創(chuàng)建資源對象
        SellTickets st = new SellTickets();

        //創(chuàng)建線程對象
        Thread t1 = new Thread(st, "窗口1");
        Thread t2 = new Thread(st, "窗口2");
        Thread t3 = new Thread(st, "窗口3");

        //啟動(dòng)線程
        t1.start();
        t2.start();
        t3.start();
    }
}

在SellTicket類中添加sleep方法,延遲一下線程,拖慢一下執(zhí)行的速度

通過加入延遲后,就產(chǎn)生了連個(gè)問題:

A:相同的票賣了多次

CPU的一次操作必須是原子性(最簡單的)的 (在讀取tickets--的原來的數(shù)值和減1之后的中間擠進(jìn)了兩個(gè)線程而出現(xiàn)重復(fù))

B:出現(xiàn)了負(fù)數(shù)票

隨機(jī)性和延遲導(dǎo)致的 (三個(gè)線程同時(shí)擠進(jìn)一個(gè)循環(huán)里,tickets--的減法操作有可能在同一個(gè)循環(huán)中被執(zhí)行了多次而出現(xiàn)越界的情況,比如說 tickets要大于0卻越界到了-1)

也就是說,線程1執(zhí)行的同時(shí)線程2也可能在執(zhí)行,而不是線程1執(zhí)行的時(shí)候線程2不能執(zhí)行。

我們先要知道一下哪些問題會導(dǎo)致出問題:

而且這些原因也是以后我們判斷一個(gè)程序是否會有線程安全問題的標(biāo)準(zhǔn)

A:是否是多線程環(huán)境

B:是否有共享數(shù)據(jù)

C:是否有多條語句操作共享數(shù)據(jù)

我們對照起來,我們的程序確實(shí)存在上面的問題,因?yàn)樗鼭M足上面的條件

那我們怎么來解決這個(gè)問題呢?

把多條語句操作共享數(shù)據(jù)的代碼給包成一個(gè)整體,讓某個(gè)線程在執(zhí)行的時(shí)候,別人不能來執(zhí)行

Java給我們提供了:同步機(jī)制

//同步代碼塊:

synchronized(對象){
    需要同步的代碼;
}

同步的好處

同步的出現(xiàn)解決了多線程的安全問題

同步的弊端

當(dāng)線程相當(dāng)多時(shí),因?yàn)槊總€(gè)線程都會去判斷同步上的鎖,這是很耗費(fèi)資源的,無形中會降低程序的運(yùn)行效率

概述:

A:同步代碼塊的鎖對象是誰呢?

任意對象

B:同步方法的格式及鎖對象問題?

把同步關(guān)鍵字加在方法上

同步方法的鎖對象是誰呢?

this

C:靜態(tài)方法及鎖對象問題?

靜態(tài)方法的鎖對象是誰呢?

類的字節(jié)碼文件對象。

我們使用 synchronized 改進(jìn)我們上面的程序,前面線程安全的問題,

public class SellTickets implements Runnable {
    private int tickets = 100;

    //創(chuàng)建鎖對象
    //把這個(gè)關(guān)鍵的鎖對象定義到run()方法(獨(dú)立于線程之外),造成同一把鎖
    private Object obj = new Object();

    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() 
                                       + "正在出售第" + (tickets--) + "張票");
                }
            }
        }
    }
}
(八) lock鎖的概述和使用

為了更清晰的表達(dá)如何加鎖和釋放鎖,JDK5以后提供了一個(gè)新的鎖對象Lock

(可以更清晰的看到在哪里加上了鎖,在哪里釋放了鎖,)

void lock() 加鎖

void unlock() 釋放鎖
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTickets2 implements Runnable {

    private int tickets = 100;

    private Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lock.lock();
                ;
                if (tickets > 0) {
                    try {
                        Thread.sleep(150);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票");
                }
            } finally {
                lock.unlock();
            }
        }
    }
}
(九) 死鎖問題 (簡單認(rèn)識)

同步弊端

效率低

如果出現(xiàn)了同步嵌套,就容易產(chǎn)生死鎖問題

死鎖問題

是指兩個(gè)或者兩個(gè)以上的線程在執(zhí)行的過程中,因爭奪資源產(chǎn)生的一種互相等待現(xiàn)象

(十) 等待喚醒機(jī)制

我們前面假定的電影院場景,其實(shí)還是有一定局限的,我們所假定的票數(shù)是一定的,但是實(shí)際生活中,往往是一種供需共存的狀態(tài),例如去買早點(diǎn),當(dāng)消費(fèi)者買走一些后,而作為生產(chǎn)者的店家就會補(bǔ)充一些商品,為了研究這一種場景,我們所要學(xué)習(xí)的就是Java的等待喚醒機(jī)制

生產(chǎn)者消費(fèi)者問題(英語:Producer-consumer problem),也稱有限緩沖問題(英語:Bounded-buffer problem),是一個(gè)多進(jìn)程同步問題的經(jīng)典案例。該問題描述了共享固定大小緩沖區(qū)的兩個(gè)進(jìn)程——即所謂的“生產(chǎn)者”和“消費(fèi)者”——在實(shí)際運(yùn)行時(shí)會發(fā)生的問題。生產(chǎn)者的主要作用是生成一定量的數(shù)據(jù)放到緩沖區(qū)中,然后重復(fù)此過程。與此同時(shí),消費(fèi)者也在緩沖區(qū)消耗這些數(shù)據(jù)。該問題的關(guān)鍵就是要保證生產(chǎn)者不會在緩沖區(qū)滿時(shí)加入數(shù)據(jù),消費(fèi)者也不會在緩沖區(qū)中空時(shí)消耗數(shù)據(jù)。

我們用通俗一點(diǎn)的話來解釋一下這個(gè)問題

Java使用的是搶占式調(diào)度模型

A:如果消費(fèi)者先搶到了CPU的執(zhí)行權(quán),它就會去消費(fèi)數(shù)據(jù),但是現(xiàn)在的數(shù)據(jù)是默認(rèn)值,如果沒有意義,應(yīng)該等數(shù)據(jù)有意義再消費(fèi)。就好比買家進(jìn)了店鋪早點(diǎn)卻還沒有做出來,只能等早點(diǎn)做出來了再消費(fèi)

B:如果生產(chǎn)者先搶到CPU的執(zhí)行權(quán),它就回去生產(chǎn)數(shù)據(jù),但是,當(dāng)它產(chǎn)生完數(shù)據(jù)后,還繼續(xù)擁有執(zhí)行權(quán),它還能繼續(xù)產(chǎn)生數(shù)據(jù),這是不合理的,你應(yīng)該等待消費(fèi)者將數(shù)據(jù)消費(fèi)掉,再進(jìn)行生產(chǎn)。 這又好比,店鋪不能無止境的做早點(diǎn),賣一些,再做,避免虧本

梳理思路

A:生產(chǎn)者 —— 先看是否有數(shù)據(jù),有就等待,沒有就生產(chǎn),生產(chǎn)完之后通知消費(fèi)者來消費(fèi)數(shù)據(jù)

B:消費(fèi)者 —— 先看是否有數(shù)據(jù),有就消費(fèi),沒有就等待,通知生產(chǎn)者生產(chǎn)數(shù)據(jù)

解釋喚醒——讓線程池中的線程具備執(zhí)行資格

Object類提供了三個(gè)方法:

//等待
wait()
//喚醒單個(gè)線程
notify()
//喚醒所有線程
notifyAll()

注意:這三個(gè)方法都必須在同步代碼塊中執(zhí)行 (例如synchronized塊),同時(shí)在使用時(shí)必須標(biāo)明所屬鎖,這樣才可以得出這些方法操作的到底是哪個(gè)鎖上的線程

為什么這些方法不定義在Thread類中呢 ?

這些方法的調(diào)用必須通過鎖對象調(diào)用,而我們剛才使用的鎖對象是任意鎖對象。

所以,這些方法必須定義在Object類中。

我們來寫一段簡單的代碼實(shí)現(xiàn)等待喚醒機(jī)制

public class Student {
    String name;
    int age;
    boolean flag;// 默認(rèn)情況是沒有數(shù)據(jù)(false),如果是true,說明有數(shù)據(jù)

    public Student() {
    }
}
public class SetThread implements Runnable {
    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true){
            synchronized (s) {
                //判斷有沒有數(shù)據(jù)
                //如果有數(shù)據(jù),就wait
                if (s.flag) {
                    try {
                        s.wait(); //t1等待,釋放鎖
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //沒有數(shù)據(jù),就生產(chǎn)數(shù)據(jù)
                if (x % 2 == 0) {
                    s.name = "admin";
                    s.age = 20;
                } else {
                    s.name = "User";
                    s.age = 30;
                }
                x++;
                //現(xiàn)在數(shù)據(jù)就已經(jīng)存在了,修改標(biāo)記
                s.flag = true;

                //喚醒線程
                //喚醒t2,喚醒并不表示你立馬可以執(zhí)行,必須還得搶CPU的執(zhí)行權(quán)。
                s.notify();
            }
        }
    }
}
package cn.bwh_05_Notify;

public class GetThread implements Runnable {
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true){
            synchronized (s){
                //如果沒有數(shù)據(jù),就等待
                if (!s.flag){
                    try {
                        s.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(s.name + "---" + s.age);

                //修改標(biāo)記
                s.flag = false;
                //喚醒線程t1
                s.notify();
            }
        }
    }
}
package cn.bwh_05_Notify;

public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();

        //設(shè)置和獲取的類
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //線程類
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //啟動(dòng)線程
        t1.start();
        t2.start();
    }
}
//運(yùn)行結(jié)果依次交替出現(xiàn)

生產(chǎn)者消費(fèi)者之等待喚醒機(jī)制代碼優(yōu)化

最終版代碼(在Student類中有大改動(dòng),然后GetThread類和SetThread類簡潔很多)

public class Student {
    private String name;
    private int age;
    private boolean flag;

    public synchronized void set(String name, int age) {
        if (this.flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        this.name = name;
        this.age = age;

        this.flag = true;
        this.notify();
    }

    public synchronized void get() {
        if (!this.flag) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println(this.name + "---" + this.age);

        this.flag = false;
        this.notify();
    }
}
public class SetThread implements Runnable {
    private Student s;
    private int x = 0;

    public SetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true) {
            if (x % 2 == 0) {
                s.set("admin", 20);
            } else {
                s.set("User", 30);
            }
            x++;
        }
    }
}
public class GetThread implements Runnable{
    private Student s;

    public GetThread(Student s) {
        this.s = s;
    }

    @Override
    public void run() {
        while (true){
            s.get();
        }
    }
}
public class StudentTest {
    public static void main(String[] args) {
        Student s = new Student();
        //設(shè)置和獲取的類

        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        t1.start();
        t2.start();
    }
}

最終版代碼特點(diǎn):

把Student的成員變量給私有的了。

把設(shè)置和獲取的操作給封裝成了功能,并加了同步。

設(shè)置或者獲取的線程里面只需要調(diào)用方法即可

(十一) 線程池

程序啟動(dòng)一個(gè)新線程成本是比較高的,因?yàn)樗婕暗揭c操作系統(tǒng)進(jìn)行交互。而使用線程池可以很好的提高性能,尤其是當(dāng)程序中要?jiǎng)?chuàng)建大量生存期很短的線程時(shí),更應(yīng)該考慮使用線程池

線程池里的每一個(gè)線程代碼結(jié)束后,并不會死亡,而是再次回到線程池中成為空閑狀態(tài),等待下一個(gè)對象來使用

在JDK5之前,我們必須手動(dòng)實(shí)現(xiàn)自己的線程池,從JDK5開始,Java內(nèi)置支持線程池

JDK5新增了一個(gè)Executors工廠類來產(chǎn)生線程池,有如下幾個(gè)方法
//創(chuàng)建一個(gè)具有緩存功能的線程池
//緩存:百度瀏覽過的信息再次訪問
public static?ExecutorService newCachedThreadPool()

//創(chuàng)建一個(gè)可重用的,具有固定線程數(shù)的線程池
public static?ExecutorService newFixedThreadPool(intnThreads)
??                     
//創(chuàng)建一個(gè)只有單線程的線程池,相當(dāng)于上個(gè)方法的參數(shù)是1?
public static?ExecutorService newSingleThreadExecutor()
??                     
這些方法的返回值是ExecutorService對象,該對象表示一個(gè)線程池,可以執(zhí)行Runnable對象或者Callable對象代表的線程。它提供了如下方法

Future submit(Runnable task)
 Future submit(Callable task)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorDemo {
    public static void main(String[] args) {
        //創(chuàng)建一個(gè)線程池對象,控制要?jiǎng)?chuàng)建幾個(gè)線程對象
        ExecutorService pool = Executors.newFixedThreadPool(2);

        //可以執(zhí)行Runnalble對象或者Callable對象代表的線程
        pool.submit(new MyRunnable());
        pool.submit(new MyRunnable());

        //結(jié)束線程池
        pool.shutdown();
    }
}
(十二) 匿名內(nèi)部類的方式實(shí)現(xiàn)多線程程序

匿名內(nèi)部類的格式:

new 類名或者接口名( ) {
              重寫方法;
          };

本質(zhì):是該類或者接口的子類對象

public class ThreadDemo {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + i);
                }
            }
        }.start();
    }
}
public class RunnableDemo {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName() + i);
                }
            }
        }).start();
    }
}
(十三) 定時(shí)器

定時(shí)器是一個(gè)應(yīng)用十分廣泛的線程工具,可用于調(diào)度多個(gè)定時(shí)任務(wù)以后臺線程的方式執(zhí)行。在Java中,可以通過Timer和TimerTask類來實(shí)現(xiàn)定義調(diào)度的功能

Timer

·public Timer()

public void schedule(TimerTask task, long delay)

public void schedule(TimerTask task,long delay,long period)

TimerTask

abstract void run()

public boolean cancel()

開發(fā)中

Quartz是一個(gè)完全由java編寫的開源調(diào)度框架

結(jié)尾:

如果內(nèi)容中有什么不足,或者錯(cuò)誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !^_^

如果能幫到你的話,那就來關(guān)注我吧!(系列文章均會在公眾號第一時(shí)間更新)

在這里的我們素不相識,卻都在為了自己的夢而努力 ?

一個(gè)堅(jiān)持推送原創(chuàng)Java技術(shù)的公眾號:理想二旬不止

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/75448.html

相關(guān)文章

  • JAVA 線程和并發(fā)基礎(chǔ)

    摘要:線程可以被稱為輕量級進(jìn)程。一個(gè)守護(hù)線程是在后臺執(zhí)行并且不會阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。在的線程中并沒有可供任何對象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發(fā)編程網(wǎng) - 鄭旭東 校對:方騰飛 多...

    vboy1010 評論0 收藏0
  • JAVA 線程和并發(fā)基礎(chǔ)面試問答

    摘要:多線程和并發(fā)問題是技術(shù)面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級進(jìn)程。一個(gè)守護(hù)線程是在后臺執(zhí)行并且不會阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。 多線程和并發(fā)問題是 Java 技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握J(rèn)ava多線程基礎(chǔ)知識來對應(yīng)日后碰到的問題。(...

    dreamans 評論0 收藏0
  • 40道阿里巴巴JAVA研發(fā)崗線程面試題詳解,你能答出

    摘要:但是單核我們還是要應(yīng)用多線程,就是為了防止阻塞。多線程可以防止這個(gè)問題,多條線程同時(shí)運(yùn)行,哪怕一條線程的代碼執(zhí)行讀取數(shù)據(jù)阻塞,也不會影響其它任務(wù)的執(zhí)行。 1、多線程有什么用?一個(gè)可能在很多人看來很扯淡的一個(gè)問題:我會用多線程就好了,還管它有什么用?在我看來,這個(gè)回答更扯淡。所謂知其然知其所以然,會用只是知其然,為什么用才是知其所以然,只有達(dá)到知其然知其所以然的程度才可以說是把一個(gè)知識點(diǎn)...

    lpjustdoit 評論0 收藏0
  • 想進(jìn)大廠?50個(gè)線程面試題,你會少?【后25題】(二)

    摘要:大多數(shù)待遇豐厚的開發(fā)職位都要求開發(fā)者精通多線程技術(shù)并且有豐富的程序開發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問題在面試中經(jīng)常會被提到。掌握了這些技巧,你就可以輕松應(yīng)對多線程和并發(fā)面試了。進(jìn)入等待通行準(zhǔn)許時(shí),所提供的對象。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗(yàn)及面試題,往往都是一大堆技術(shù)題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關(guān)線程的問題。Java語言一個(gè)重要的特點(diǎn)就...

    caozhijian 評論0 收藏0
  • 超詳細(xì)的Java面試題總結(jié)(二)之Java基礎(chǔ)知識篇

    摘要:超詳細(xì)的面試題總結(jié)一之基本知識多線程和虛擬機(jī)創(chuàng)建線程有幾種不同的方式你喜歡哪一種為什么繼承類實(shí)現(xiàn)接口應(yīng)用程序可以使用框架來創(chuàng)建線程池實(shí)現(xiàn)接口。死亡線程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線程結(jié)束生命周期。死亡的線程不可再次復(fù)生。 超詳細(xì)的Java面試題總結(jié)(一)之Java基本知識 多線程和Java虛擬機(jī) 創(chuàng)建線程有幾種不同的方式?你喜歡哪一種?為什么? 繼承Thread類 實(shí)現(xiàn)R...

    wangjuntytl 評論0 收藏0
  • 想進(jìn)大廠?50個(gè)線程面試題,你會少?(一)

    摘要:下面是線程相關(guān)的熱門面試題,你可以用它來好好準(zhǔn)備面試。線程安全問題都是由全局變量及靜態(tài)變量引起的。持有自旋鎖的線程在之前應(yīng)該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗(yàn)及面試題,往往都是一大堆技術(shù)題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關(guān)線程的問題。Java語言一個(gè)重要的特點(diǎn)就是內(nèi)置了對并發(fā)的支持,讓Java大受企業(yè)和程序員...

    wow_worktile 評論0 收藏0

發(fā)表評論

0條評論

高璐

|高級講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<