成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java多線程&高并發(fā)

SQC / 661人閱讀

摘要:線程啟動(dòng)規(guī)則對象的方法先行發(fā)生于此線程的每一個(gè)動(dòng)作。所以局部變量是不被多個(gè)線程所共享的,也就不會(huì)出現(xiàn)并發(fā)問題。通過獲取到數(shù)據(jù),放入當(dāng)前線程處理完之后將當(dāng)前線程中的信息移除。主線程必須在啟動(dòng)其他線程后立即調(diào)用方法。

一、線程安全性
定義:當(dāng)多個(gè)線程訪問某個(gè)類時(shí),不管運(yùn)行時(shí)環(huán)境采用何種調(diào)度方式,或者這些線程將如何交替執(zhí)行,并且在主調(diào)代碼中不需要任何額外的同步或協(xié)同,這個(gè)類都能表現(xiàn)出正確的行為,那么就稱這個(gè)類是線程安全的。

1. 原子性:提供了互斥訪問,同一時(shí)刻只能有一個(gè)線程來對它進(jìn)行訪問。

Atomic包:

AtomicXXX:CAS、Unsafe.compareAndSwapInt

AtomicLong、LongAdder

AtomicReference、AtomicReferenceFieldUpdater

AtomicStampReference:CAS的ABA問題

原子性 - synchronized(同步鎖)
修飾代碼塊:大括號(hào)括起來的代碼,作用于調(diào)用的對象
修飾方法:整個(gè)方法,作用于調(diào)用的對象
修飾靜態(tài)方法:整個(gè)靜態(tài)方法,作用于所有對象
修飾類:括號(hào)括起來的部分,作用于所有類
原子性 - 對比
synchronized:不可中斷鎖,適合競爭不激烈,可讀性好
Lock:可中斷鎖,多樣化同步,競爭激烈時(shí)能維持常態(tài)
Atomic:競爭激烈時(shí)能維持常態(tài),比Lock性能好;只能同步一個(gè)值

2. 可見性:一個(gè)線程對主內(nèi)存的修改可以及時(shí)的被其他線程觀察到。

導(dǎo)致共享變量在線程見不可見的原因

線程交叉執(zhí)行

沖排序結(jié)合線程交叉執(zhí)行

共享變量更新后的值沒有在工作內(nèi)存與主內(nèi)存之間急事更新

synchronized、volatile
JMM關(guān)于synchronized的兩條規(guī)定:

線程解鎖前,必須把共享變量的最新制刷新到主內(nèi)存

線程加鎖前,將清空工作內(nèi)存中共享變量的值,從而使用共享變量時(shí)需要從主內(nèi)存中重新讀取最新的值(注意:加鎖與解鎖是同一把鎖

volatile - 通過加入內(nèi)存屏障禁止重排序優(yōu)化來實(shí)現(xiàn)

對volatile變量寫操作時(shí),會(huì)在寫操作后加入一條store屏障指令,將本地內(nèi)存中的共享變量值刷新到主內(nèi)存

對volatile變量讀操作時(shí),會(huì)在讀操作前加入一條load屏障指令,從主內(nèi)存中讀取共享變量

volatile變量在每次被線程訪問時(shí),都強(qiáng)迫從主內(nèi)存中讀取該變量的值,而當(dāng)變量的值發(fā)生變化時(shí),又會(huì)強(qiáng)迫線程將該變量最新的值強(qiáng)制刷新到主內(nèi)存,這樣一來,任何時(shí)候不同的線程總能看到該變量的最新值

3. 有序性:一個(gè)線程觀察其他線程中的指令執(zhí)行順序,由于指令重排序的存在,該觀察結(jié)果一般雜亂無序。

Java內(nèi)存模型中,允許編譯器和處理器對指令進(jìn)行重排序,但是重排序過程不會(huì)影響到單線程程序的執(zhí)行,卻會(huì)影響到多線程并發(fā)執(zhí)行的正確性。volatile、synchronized、Lock。
【volatile變量規(guī)則】:對一個(gè)變量的寫操作先行發(fā)生于后面對這個(gè)變量的讀操作。(如果一個(gè)線程進(jìn)行寫操作,一個(gè)線程進(jìn)行讀操作,那么寫操作會(huì)先行于讀操作。)
【傳遞規(guī)則】:如果操作A先行于操作B,而操作B又先行于操作C,那么操作A就先行于操作C。
【線程啟動(dòng)規(guī)則】:Thread對象的start方法先行發(fā)生于此線程的每一個(gè)動(dòng)作。
【線程中斷規(guī)則】:對線程interrupt方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生。
【線程終結(jié)規(guī)則】:線程中所有的操作都先行發(fā)生于線程的終止檢測,我們可以通過Thread.join()方法結(jié)束、Thread.isAlive()方法的返回值手段檢測到線程已經(jīng)終止執(zhí)行。
【對象終結(jié)規(guī)則】:一個(gè)對象的初始化完成先行發(fā)生于他的finalize()方法的開始。
二、發(fā)布對象
發(fā)布對象:使一個(gè)對象能夠被當(dāng)前范圍之外的代碼所用。
對象溢出:一種錯(cuò)誤的發(fā)布。當(dāng)一個(gè)對象還沒有構(gòu)造完成時(shí),就使它被其他線程所見。
三、安全發(fā)布對象
在靜態(tài)初始化函數(shù)中初始化一個(gè)對象
將對象的引用保存到volatile類型域或者AtomicReference對象中
將對象的引用保存到某個(gè)正確構(gòu)造對象的final類型域中
將對象的引用保存到一個(gè)由鎖保護(hù)的域中
/**
 * 懶漢模式
 * 雙重同步鎖單例模式
 * @author Guo
 *
 */
public class SingletonExample1 {
    
    private SingletonExample1(){
        
    }
    
    // volatile禁止指令重排
    private volatile static SingletonExample1 instance = null;
    
    public static SingletonExample1 getInstance(){
        if(instance == null){
            synchronized(SingletonExample1.class){
                if(instance == null){
                    instance = new SingletonExample1();
                }
            }
        }
        return instance;
    }

}
四、避免并發(fā)兩種方式

不可變對象

線程封閉

線程封閉: 把對象封裝到一個(gè)線程里,只有這一個(gè)線程可以看到這個(gè)對象,即使這個(gè)對象不是線程安全也不會(huì)出現(xiàn)任何線程安全問題,因?yàn)橹辉谝粋€(gè)線程里

堆棧封閉局部變量,無并發(fā)問題。棧封閉是我們編程當(dāng)中遇到的最多的線程封閉。什么是棧封閉呢?簡單的說就是局部變量。多個(gè)線程訪問一個(gè)方法,此方法中的局部變量都會(huì)被拷貝一分兒到線程棧中。所以局部變量是不被多個(gè)線程所共享的,也就不會(huì)出現(xiàn)并發(fā)問題。所以能用局部變量就別用全局的變量,全局變量容易引起并發(fā)問題。

ThreadLocal線程封閉:比較推薦的線程封閉方式。
【ThreadLocal結(jié)合filter完成數(shù)據(jù)保存到ThreadLocal里,線程隔離。】通過filter獲取到數(shù)據(jù),放入ThreadLocal, 當(dāng)前線程處理完之后interceptor將當(dāng)前線程中的信息移除。使用ThreadLocal是實(shí)現(xiàn)線程封閉的最好方法。ThreadLocal內(nèi)部維護(hù)了一個(gè)Map,Map的key是每個(gè)線程的名稱,而Map的值就是我們要封閉的對象。每個(gè)線程中的對象都對應(yīng)著Map中一個(gè)值,也就是ThreadLocal利用Map實(shí)現(xiàn)了對象的線程封閉

五、線程不安全類與寫法
【線程不安全】:如果一個(gè)類類對象同時(shí)可以被多個(gè)線程訪問,如果沒有做同步或者特殊處理就會(huì)出現(xiàn)異?;蛘哌壿嬏幚礤e(cuò)誤。
【1. 字符串拼接】:
StringBuilder(線程不安全)、
StringBuffer(線程安全)
【2. 日期轉(zhuǎn)換】:
SimpleDateFormat(線程不安全,最好使用局部變量[堆棧封閉]保證線程安全)
JodaTime推薦使用(線程安全)
【3. ArrayList、HashSet、HashMap等Collections】:
ArrayList(線程不安全)
HashSet(線程不安全)
HashMap(線程不安全)
【**同步容器**synchronized修飾】
Vector、Stack、HashTable
Collections.synchronizedXXX(List、Set、Map)
【**并發(fā)容器** J.U.C】
ArrayList -> CopyOnWriteArrayList:(讀時(shí)不加鎖,寫時(shí)加鎖,避免復(fù)制多個(gè)副本出來將數(shù)據(jù)搞亂)寫操作時(shí)復(fù)制,當(dāng)有新元素添加到CopyOnWriteArrayList中時(shí),先從原有的數(shù)組中拷貝一份出來,在新的數(shù)組上進(jìn)行寫操作,寫完之后再將原來的數(shù)組指向新的數(shù)組。

HashSet、TreeSet -> CopyOnWriteArraySet、ConcurrentSkipListSet
HashMap、TreeMap -> ConcurrentHashMap、ConcurrentSkipListMap
相比ConcurrentHashMap,ConcurrentSkipListMap具有如下優(yōu)勢:

ConcurrentSkipListMap的存取速度是ConcurrentSkipListMap的4倍左右

ConcurrentSkipListMap的key是有序的

ConcurrentSkipListMap支持更高的并發(fā)(它的存取時(shí)間和線程數(shù)幾乎沒有關(guān)系,更高并發(fā)的場景下越能體現(xiàn)出優(yōu)勢)

六、安全共享對象策略 - 總結(jié)

線程限制:一個(gè)被線程限制的對象,由線程獨(dú)占,并且只能被占有它的線程修改

共享只讀:一個(gè)共享只讀的對象,在沒有額外同步的情況下,可以被多個(gè)線程并發(fā)訪問,但是任何線程都不能修改它

線程安全對象:一個(gè)線程安全的對象或者容器,在內(nèi)部通過同步機(jī)制來保證線程安全,所以其他線程無需額外的同步就可以通過公共接口隨意訪問它

被守護(hù)對象:被守護(hù)對象只能通過獲取特定鎖來訪問

七、J.U.C 之 AQS 7.1、 AQS

AQS:AbstractQueneSynchronizer

使用Node實(shí)現(xiàn)FIFO隊(duì)列,可以用于構(gòu)建鎖或者其他同步裝置的基礎(chǔ)框架

利用int類型表示狀態(tài)

使用方法是繼承

子類通過繼承并通過實(shí)現(xiàn)它的方法管理其狀態(tài){ acquire和release }的方法操縱狀態(tài)

可以同時(shí)實(shí)現(xiàn)排它鎖和共享鎖模式(獨(dú)占、共享)

7.2、 AQS的同步組件如下:
7.2.1、CountDownLatch:閉鎖,通過計(jì)數(shù)來保證線程是否一直阻塞.
CountDownLatch是通過一個(gè)計(jì)數(shù)器來實(shí)現(xiàn)的,計(jì)數(shù)器的初始值為線程的數(shù)量。每當(dāng)一個(gè)線程完成了自己的任務(wù)后,計(jì)數(shù)器的值就會(huì)減1。當(dāng)計(jì)數(shù)器值到達(dá)0時(shí),它表示所有的線程已經(jīng)完成了任務(wù),然后在閉鎖上等待的線程就可以恢復(fù)執(zhí)行任務(wù)。構(gòu)造器中的計(jì)數(shù)值(count)實(shí)際上就是閉鎖需要等待的線程數(shù)量。這個(gè)值只能被設(shè)置一次,而且CountDownLatch沒有提供任何機(jī)制去重新設(shè)置這個(gè)計(jì)數(shù)值。

與CountDownLatch的第一次交互是主線程等待其他線程。主線程必須在啟動(dòng)其他線程后立即調(diào)用CountDownLatch.await()方法。這樣主線程的操作就會(huì)在這個(gè)方法上阻塞,直到其他線程完成各自的任務(wù)。

其他N 個(gè)線程必須引用閉鎖對象,因?yàn)樗麄冃枰ㄖ狢ountDownLatch對象,他們已經(jīng)完成了各自的任務(wù)。這種通知機(jī)制是通過 CountDownLatch.countDown()方法來完成的;每調(diào)用一次這個(gè)方法,在構(gòu)造函數(shù)中初始化的count值就減1。所以當(dāng)N個(gè)線程都調(diào) 用了這個(gè)方法,count的值等于0,然后主線程就能通過await()方法,恢復(fù)執(zhí)行自己的任務(wù)。

解釋一下CountDownLatch概念?
`CountDownLatch`和 `CyclicBarrier`的不同之處?
給出一些CountDownLatch使用的例子?
 CountDownLatch類中主要的方法?

public class CountDownLatchExample1 {
    
    // 線程數(shù)
    private final static int threadCount = 200;
    
    public static void main(String[] args) throws InterruptedException{
        // 使用線程池進(jìn)行調(diào)度
        ExecutorService exec = Executors.newCachedThreadPool();
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    test(threadNum);
                } catch (Exception e) {
                    System.out.println("exception:" + e);
                }finally{
                    countDownLatch.countDown(); // 計(jì)數(shù)器減一
                }
            });
        }
        countDownLatch.await(10, TimeUnit.MILLISECONDS);
        System.out.println("===finished===");
        exec.shutdown();
    }
    
    
    private static void test(int threadNum) throws InterruptedException{
        Thread.sleep(100);
        System.out.println("threadNum:" + threadNum);
    }
    

}
7.2.2、Semaphore(信號(hào)量):可以控制同一時(shí)間并發(fā)線程的數(shù)目
主要函數(shù):acquire、release、tryAcquire
    
public class SemaphoreExample1 {
    
    // 線程數(shù)
    private final static int threadCount = 20;
    
    public static void main(String[] args) throws InterruptedException{
        // 使用線程池進(jìn)行調(diào)度
        ExecutorService exec = Executors.newCachedThreadPool();
        //并發(fā)控制(允許并發(fā)數(shù)20)
        final Semaphore semaphore = new Semaphore(3);
        
        final CountDownLatch countDownLatch = new CountDownLatch(threadCount);
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            exec.execute(() -> {
                try {
                    if(semaphore.tryAcquire(5, TimeUnit.SECONDS)){
                        test(threadNum);
                        semaphore.release();
                    }
                    /** 多個(gè)許可:在代碼中一共有10個(gè)許可,每次執(zhí)行semaphore.acquire(5);
                     * 代碼時(shí)耗費(fèi)掉5個(gè),所以20/5=4,
                     * 說明同一時(shí)間只有4個(gè)線程允許執(zhí)行acquire()和release()之間的代碼。
                     * */
//                    semaphore.acquire(3); // 獲取許可
//                    test(threadNum);
//                    semaphore.release(3); // 釋放許可
                } catch (Exception e) {
                    System.out.println("exception:" + e);
                }finally{
                    countDownLatch.countDown(); // 計(jì)數(shù)器減一
                }
            });
        }
//        countDownLatch.await(100, TimeUnit.MILLISECONDS);
        System.out.println("===finished===");
        exec.shutdown();
    }
    
    
    private static void test(int threadNum) throws InterruptedException{
        System.out.println("threadNum:" + threadNum);
        Thread.sleep(1000);
    }
    

}
7.2.3、CyclicBarrier:可以完成多個(gè)線程之間相互等待,只有當(dāng)每個(gè)線程都準(zhǔn)備就緒后,才能各自繼續(xù)往下執(zhí)行
應(yīng)用場景:需要所有的子任務(wù)都完成時(shí),才執(zhí)行主任務(wù),這個(gè)時(shí)候就可以選擇使用CyclicBarrier。

簡單理解【`人滿發(fā)車`】:
長途汽車站提供長途客運(yùn)服務(wù)。
當(dāng)?shù)却嚨某丝偷竭_(dá)20人時(shí),汽車站就會(huì)發(fā)出一輛長途汽車,讓這20個(gè)乘客上車走人。
等到下次等待的乘客又到達(dá)20人是,汽車站就會(huì)又發(fā)出一輛長途汽車。
public class CyclicBarrierExample1 {
    
    // 線程數(shù)
    private final static int threadCount = 10;
    
    // 屏障的線程數(shù)目 5 
    private static CyclicBarrier barrier = new CyclicBarrier(5, () -> {
        System.out.println("===continue===");
    });
    
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool(); 
        for (int i = 0; i < threadCount; i++) {
            final int threadNum = i;
            Thread.sleep(500);
            executorService.execute(() -> {
                try {
                    race(threadNum);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        
        
    }

    private static void race(int threadNum) throws Exception {
        Thread.sleep(1000);
        System.out.println("===" + threadNum + " is ready.");
        try{
            barrier.await(2000, TimeUnit.MILLISECONDS);
        }catch(Exception e){
            System.out.println("e:"+e);
        }
        System.out.println("===" + threadNum + " continue");
    }

}
7.2.4、ReentrantLock
1. api:
    - lock()
    - unlock()
    - tryLock()
   private static Lock lock = new ReentrantLock();
   private static void test(int threadNum){
           lock.lock();
           try{
               count++;
           }finally{
               lock.unlock();
           }
       }
2. ReentrantLock和synchronized的區(qū)別
    - 1. `可重入性`
    - 2. `鎖的實(shí)現(xiàn)`:synchronized是jvm實(shí)現(xiàn),ReentrantLock是jdk實(shí)現(xiàn)
    - 3. `性能區(qū)別`
    - 4. `功能方面的區(qū)別`
3. ReentrantLock獨(dú)有的功能
    - 1. 可指定是公平鎖還是非公平鎖,synchronized只能是非公平鎖(公平鎖:先等待的線程先獲得鎖)
    - 2. 提供了一個(gè)Condition類,可以分組喚醒需要喚醒的線程
    - 3. 提供能夠中斷等待鎖的線程的機(jī)制,lock.lockInterruptibly()
4. ReentrantReadWriteLock
5. StampedLock
6. 鎖的使用
   - 當(dāng)只有少量競爭者線程的時(shí)候,`synchronized`是一個(gè)很好的通用的鎖的實(shí)現(xiàn)(synchronized不會(huì)引發(fā)死鎖,jvm會(huì)自動(dòng)解鎖)
   - 競爭者線程不少,但是線程增長的趨勢是可以預(yù)估的,這時(shí)候使用`ReentrantLock`是一個(gè)很好的通用的鎖的實(shí)現(xiàn)
7.2.5、Condition
public class LockExample3 {
public static void main(String[] args){
    ReentrantLock reentrantLock = new ReentrantLock();
    Condition condition = reentrantLock.newCondition();
    int u=1;
    
    
    new Thread(() -> {
        try{
            reentrantLock.lock();
            System.out.println("wait signal"); // 1
            condition.await();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        System.out.println("get signal");
        reentrantLock.unlock();
    }).start();
    
    new Thread(() -> {
        reentrantLock.lock();
        System.out.println("get lock");
        try{
            Thread.sleep(3000);
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        condition.signalAll();
        System.out.println("send signal");
        reentrantLock.unlock();
    }).start();
    
    
}

}
7.2.6、FutureTask
    創(chuàng)建線程兩種方式繼承Thread,實(shí)現(xiàn)Runnable接口,這兩種方式,在任務(wù)執(zhí)行完畢之后獲取不到執(zhí)行結(jié)果
    FutureTask、Callable可以獲取到執(zhí)行結(jié)果
    1. Callable和Runnable對比
    2. Future接口
    3. FutureTask
    ```
    public static void main(String[] args) throws InterruptedException, ExecutionException {
    FutureTask futureTask = new FutureTask(new Callable() {
        @Override
        public String call() throws Exception {
            System.out.println("do something in callable...");
            Thread.sleep(3000);
            return "Done";
        }
    });
    
    new Thread(futureTask).start();
    System.out.println("do something in main...");
    Thread.sleep(1000);
    String result = futureTask.get();
    System.out.println("result:"+result);
}

}

7.2.7、Fork/Join框架:將大模塊切分成多個(gè)小模塊進(jìn)行計(jì)算

八、線程池
初始化好線程池實(shí)例之后,將任務(wù)丟進(jìn)去等待調(diào)度執(zhí)行。
8.1、Thread弊端

每次new Thread都要新建對象,性能差

線程缺乏統(tǒng)一管理,可能無限制的新建線程,相互競爭,有可能占用過多的系統(tǒng)資源導(dǎo)致死機(jī)或者OOM

缺少更多功能,如更多執(zhí)行,定期執(zhí)行,線程中斷

8.2、線程池的好處

可以重用存在的線程,減少對象的創(chuàng)建、消亡的開銷,性能佳

可以有效的控制最大并發(fā)數(shù),提供系統(tǒng)資源利用率,同時(shí)可以避免過多的資源競爭,避免阻塞

提供定時(shí)執(zhí)行、定期執(zhí)行、單線程、并發(fā)數(shù)控制等功能

ThreadPoolExecutor的初始化參數(shù)】
corePoolSize:核心線程數(shù)量
maximumPoolSize:縣城最大線程數(shù)
workQueue:阻塞隊(duì)列,存儲(chǔ)等待執(zhí)行的任務(wù),很重要,會(huì)對線程池運(yùn)行過程產(chǎn)生重大影響
keepAliveTime:線程沒有任務(wù)執(zhí)行時(shí),最多保持多久時(shí)間終止
unit:keepAliveTime的時(shí)間單位
hreadFactory:線程工廠,用來創(chuàng)建線程
rejectHandler:當(dāng)拒絕處理任務(wù)時(shí)的策略

線程池-ThreadPoolExecutor狀態(tài)

線程池-ThreadPoolExecutor方法

1. execute():提交任務(wù),交給線程池執(zhí)行
2. submit():提交任務(wù)能夠返回執(zhí)行結(jié)果execute + Future
3. shutdown():關(guān)閉線程池,等待任務(wù)都執(zhí)行完
4. shutdownNow():關(guān)閉線程池,不等待任務(wù)執(zhí)行完
5. getTaskCount():線程池已執(zhí)行和未執(zhí)行的任務(wù)總數(shù)
6. getCompletedTaskCount():已完成的任務(wù)總數(shù)
7. getPoolSize():線程池當(dāng)前的線程數(shù)量
8. getActiveCount:當(dāng)前線程池中正在執(zhí)行任務(wù)的線程數(shù)量
8.3、線程池 - Executors框架(創(chuàng)建線程池)

Executors.newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池,如果線程池長度超過了處理的需要可以靈活回收空閑線程,如果沒有可以回收的,那么就新建線程

public static void main(String[] args) {
        ExecutorService executorService = Executors.newCachedThreadPool();
        // 往線程池中放任務(wù)
        for (int i = 0; i < 10; i++) {
            final int index = i; // 任務(wù)的序號(hào)
            executorService.execute(() -> {
                System.out.println("===task:"+index);
            });
        }
        executorService.shutdown(); // 關(guān)閉線程池
    }

Executors.newFixedThreadPool:創(chuàng)建的是一個(gè)定長的線程池,可以控制線程的最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待

Executors.newScheduledThreadPool:創(chuàng)建的也是定長線程池,支持定時(shí)以及周期性的任務(wù)執(zhí)行

public static void main(String[] args) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
        
        // 往線程池中放任務(wù)
        executorService.scheduleAtFixedRate(() -> {
            log.info("===sechedule run");
        }, 1, 3, TimeUnit.SECONDS); // 延遲一秒,每隔三秒執(zhí)行任務(wù)
        
        
        executorService.schedule(() -> {
            log.info("===sechedule run");
        }, 3, TimeUnit.SECONDS);
        
        executorService.shutdown(); // 關(guān)閉線程池
    }

Executors.newSingleThreadExecutor:創(chuàng)建的是一個(gè)單線程化的線程池,會(huì)用唯一的一個(gè)工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指令順序執(zhí)行(指令順序可以指定它是按照先入先出,優(yōu)先級(jí)執(zhí)行)

newSingleThreadExecutor打印結(jié)果是按照順序輸出

8.4、線程池 - 合理配置
1. CPU密集型任務(wù),就需要盡量壓榨CPU,參考可以設(shè)置為NCPU+1
2. IO密集型任務(wù),參考可以設(shè)置為2*NCPU
> NCPU = CPU的數(shù)量
> UCPU = 期望對CPU的使用率 0 ≤ UCPU ≤ 1
> W/C = 等待時(shí)間與計(jì)算時(shí)間的比率
> 如果希望處理器達(dá)到理想的使用率,那么線程池的最優(yōu)大小為:
> 線程池大小=NCPU *UCPU(1+W/C)

https://www.cnblogs.com/super...
https://www.cnblogs.com/super...

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77484.html

相關(guān)文章

  • 《深入理解java虛擬機(jī)》學(xué)習(xí)筆記系列——垃圾收集器&amp;內(nèi)存分配策略

    摘要:虛擬機(jī)所處的區(qū)域,則表示它是屬于新生代收集器還是老年代收集器。虛擬機(jī)總共運(yùn)行了分鐘,其中垃圾收集花掉分鐘,那么吞吐量就是。收集器線程所占用的數(shù)量為。 本文主要從GC(垃圾回收)的角度試著對jvm中的內(nèi)存分配策略與相應(yīng)的垃圾收集器做一個(gè)介紹。 注:還是老規(guī)矩,本著能畫圖就不BB原則,盡量將各知識(shí)點(diǎn)通過思維導(dǎo)圖或者其他模型圖的方式進(jìn)行說明。文字僅記錄額外的思考與心得,以及其他特殊情況 內(nèi)存...

    calx 評論0 收藏0
  • 深入理解 Java 線程系列(1)——一個(gè)簡單需求的并行改造 &amp; Java線程的通信問題

    摘要:所以接下來,我們需要簡單的介紹下多線程中的并發(fā)通信模型。比如中,以及各種鎖機(jī)制,均為了解決線程間公共狀態(tài)的串行訪問問題。 并發(fā)的學(xué)習(xí)門檻較高,相較單純的羅列并發(fā)編程 API 的枯燥被動(dòng)學(xué)習(xí)方式,本系列文章試圖用一個(gè)簡單的栗子,一步步結(jié)合并發(fā)編程的相關(guān)知識(shí)分析舊有實(shí)現(xiàn)的不足,再實(shí)現(xiàn)邏輯進(jìn)行分析改進(jìn),試圖展示例子背后的并發(fā)工具與實(shí)現(xiàn)原理。 本文是本系列的第一篇文章,提出了一個(gè)簡單的業(yè)務(wù)場景...

    ruicbAndroid 評論0 收藏0
  • JAVA線程機(jī)制解析-volatile&amp;synchronized

    摘要:當(dāng)一個(gè)線程持有重量級(jí)鎖時(shí),另外一個(gè)線程就會(huì)被直接踢到同步隊(duì)列中等待。 java代碼先編譯成字節(jié)碼,字節(jié)碼最后編譯成cpu指令,因此Java的多線程實(shí)現(xiàn)最終依賴于jvm和cpu的實(shí)現(xiàn) synchronized和volatile 我們先來討論一下volatile關(guān)鍵字的作用以及實(shí)現(xiàn)機(jī)制,每個(gè)線程看到的用volatile修飾的變量的值都是最新的,更深入的解釋就涉及到Java的內(nèi)存模型了,我們...

    dendoink 評論0 收藏0
  • Apache--MPMs &amp;&amp; Nginx事件驅(qū)動(dòng)

    摘要:全稱是多道處理模塊我們都知道是以模塊化方式設(shè)計(jì)的那么用來決定如何處理用戶請求的是通過一個(gè)進(jìn)程處理一個(gè)請求還是一個(gè)線程處理一個(gè)請求當(dāng)前有三種可以選擇的方式雖然有以上三種方式但是要注意在任何時(shí)間必須有一個(gè)而且只能有一個(gè)被使用那么下面就介紹一下這 MPM全稱是多道處理模塊,我們都知道apache是以模塊化方式設(shè)計(jì)的.那么MPM用來決定apache如何處理用戶請求的.是通過一個(gè)進(jìn)程處理一個(gè)請...

    ivydom 評論0 收藏0
  • Apache--MPMs &amp;&amp; Nginx事件驅(qū)動(dòng)

    摘要:全稱是多道處理模塊我們都知道是以模塊化方式設(shè)計(jì)的那么用來決定如何處理用戶請求的是通過一個(gè)進(jìn)程處理一個(gè)請求還是一個(gè)線程處理一個(gè)請求當(dāng)前有三種可以選擇的方式雖然有以上三種方式但是要注意在任何時(shí)間必須有一個(gè)而且只能有一個(gè)被使用那么下面就介紹一下這 MPM全稱是多道處理模塊,我們都知道apache是以模塊化方式設(shè)計(jì)的.那么MPM用來決定apache如何處理用戶請求的.是通過一個(gè)進(jìn)程處理一個(gè)請...

    muzhuyu 評論0 收藏0

發(fā)表評論

0條評論

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