溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java多線程是什么及如何創(chuàng)建

發(fā)布時間:2022-03-10 14:26:10 來源:億速云 閱讀:138 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“Java多線程是什么及如何創(chuàng)建”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“Java多線程是什么及如何創(chuàng)建”吧!

    1、線程池:

    什么是線程池?

    咱們也不看長篇大論,通俗的來講,線程池就是裝線程的容器,當(dāng)需要用的時候去池里面取出來,不用的時候放回去或者銷毀。這樣一個線程就可以反復(fù)的利用,通過線程的這種反復(fù)利用機制,可以有效地避免直接創(chuàng)建線程所帶來的壞處。

    線程池有什么好處?

    • 降低了資源的消耗(CPU)

    • 提高任務(wù)執(zhí)行的響應(yīng)速度

    • 提高線程的可管理性

    線程池創(chuàng)建流程圖:

    Java多線程是什么及如何創(chuàng)建

    其實通過這個圖就可以看到線程池的處理過程:

    • 有新任務(wù)進來,判斷核心線程池是否滿了,是:進入排,否:創(chuàng)建任務(wù)

    • 在等待隊列判斷是否排滿了,是:進入線程池 ,否:任務(wù)加入隊列

    • 判斷線程池是否滿了,是:拒絕執(zhí)行任務(wù),否:創(chuàng)建線程執(zhí)行

    2、創(chuàng)建線程池:

    先看一下官網(wǎng)給出的創(chuàng)建方法(部分):

    Java多線程是什么及如何創(chuàng)建

    這里介紹四種常用的創(chuàng)建類型:

    • newCacheThreadPool(創(chuàng)建一個可緩存的線程池,有任務(wù)時才會創(chuàng)建新的線程)

    • newSingleThreadExecutor(創(chuàng)建一個單線程池,線程池中只有一個線程)

    • newFixedThreadPool(int a) (創(chuàng)建固定線程數(shù)量的線程池,輸入?yún)?shù):int類型)

    • newScheduledTreadPool (創(chuàng)建一個固定長度的線程池,并且以延時或定時的方式來執(zhí)行線程)

    1、newCacheThreadPool:

    創(chuàng)建可緩存的線程對象,意思是這個任務(wù)需要幾個線程來處理,就會創(chuàng)建幾個線程:

    線程需要執(zhí)行的類:

    public class MyRunnable implements Runnable{
    
        int num;
    
        public MyRunnable(int num) {
            this.num = num;
        }
    
        @Override
        public void run() {
            
            System.out.println(Thread.currentThread().getName()+"執(zhí)行了:"+num);
        }
    }

    測試類:

    public class Test {
        public static void main(String[] args) {
    
            //創(chuàng)建單個線程池對象,里面線程只有一個
            ExecutorService cachedService = Executors.newCachedThreadPool();
    
            //執(zhí)行5個任務(wù)
            for (int i = 1; i<= 5; i++) {
                cachedService.execute(new MyRunnable(i));
            }
        }
    }

    來看看結(jié)果:

    Java多線程是什么及如何創(chuàng)建

    OK,上述代碼線程池用了5個線程來處理,那么如果我們在每次運行前加一次線程休眠會怎么樣? 在每次執(zhí)行后需要休眠0.5秒(500毫秒):

    public class Test {
        public static void main(String[] args) {
        
            //創(chuàng)建一個緩存的線程池對象
           
            ExecutorService cachedService = Executors.newCachedThreadPool();
            
            for (int i = 1; i<= 5; i++) {
                    cachedService.execute(new MyRunnable(i));
                    //線程休眠:
                    try{
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        }
    }

    看看結(jié)果:

    Java多線程是什么及如何創(chuàng)建

    小結(jié):

    • 如果沒有加線程休眠,線程池默認(rèn)會創(chuàng)建多個線程池對象來幫你完成任務(wù),執(zhí)行更快完成并且銷毀內(nèi)存,釋放資源。

    • 如果添加了線程休眠,線程池會認(rèn)為同少量的線程對象就可以完成這個任務(wù),就不會幫你創(chuàng)建多個線程對象(因為時間足夠,就沒必要再創(chuàng)建)

    2、newSingleThreadExecutor:

    這個方法是創(chuàng)建只有一個線程的線程池,不管怎么樣,多只有一個線程來幫你執(zhí)行任務(wù):

    public class Test {
        public static void main(String[] args) {
    
            //創(chuàng)建單個線程池對象,里面線程只有一個
            ExecutorService singleService = Executors.newSingleThreadExecutor();
    
            //執(zhí)行一百萬次任務(wù)
            for (int i = 1; i<= 1000000; i++) {
                singleService.execute(new MyRunnable(i));
            }
        }
    }

    看看結(jié)果:

    Java多線程是什么及如何創(chuàng)建

    對吧,執(zhí)行了1000000次也是一個線程在執(zhí)行,因為這個線程池里面只有一個線程呀。

    3、newFixedThreadPool(int a):

    這個方法就是創(chuàng)建固定線程數(shù)的線程池,比如我要一個這個池里面有10個線程,在后面輸入?yún)?shù)即可:

    public class Test {
        public static void main(String[] args) {
    
            //線程池創(chuàng)建固定數(shù)量的線程對象來執(zhí)行任務(wù),這里創(chuàng)建10個線程對象,由線程池管理生命周期
            ExecutorService singleService = Executors.newFixedThreadPool(10);
            //執(zhí)行10個任務(wù)
            for (int i = 1; i<= 100; i++) {
                singleService.execute(new MyRunnable(i));
            }
        }
    }

    看看結(jié)果:

    Java多線程是什么及如何創(chuàng)建

    4、newScheduledTreadPool :

    創(chuàng)建一個固定長度的線程池,并且以延時或定時的方式來執(zhí)行線程,也就是說使用這個方法創(chuàng)建的線程池可以自定義每次執(zhí)行的時間:

    Demo:

    public class MyRunnable implements Runnable{
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"延遲5秒執(zhí)行,并且每2秒執(zhí)行一次該任務(wù):");
        }
    }

    測試類:

    public class Test {
        public static void main(String[] args) {
    
            //線程池創(chuàng)建一個定時任務(wù)的線程對象
            ScheduledExecutorService service = Executors.newScheduledThreadPool(4);
            /**
             *定時器執(zhí)行的任務(wù),并且按周期執(zhí)行
             * 參數(shù)1:線程任務(wù)
             * 參數(shù)2:5秒之后開始執(zhí)行
             * 參數(shù)3:執(zhí)行后每2秒為一個周期去循環(huán)執(zhí)行
             * 參數(shù)4:時間單位。枚舉類型,我這指定秒(可以參考API)
             */
            service.scheduleAtFixedRate(new MyRunnable(),5,1, TimeUnit.SECONDS);
        }
    }

    看看結(jié)果:

    Java多線程是什么及如何創(chuàng)建

    3、線程池創(chuàng)建自定義線程:

    當(dāng)以上四種線程池滿不足業(yè)務(wù)需求的時候,咱們也可以自定義線程池:

    先來一個線程執(zhí)行類:

    public class MyRunnable implements Runnable{
    
        int num;
    
        public MyRunnable(int i) {
    
            this.num = num;
        }
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName()+"執(zhí)行了"+num);
        }
    }

    測試類:

    public class Test {
        public static void main(String[] args) {
    
            /**
             * 參數(shù)1:線程池有5個固定的線程對象
             * 參數(shù)2:當(dāng)線程池的線程忙不過來的時候,最大線程數(shù)為7,也就是說線程對象就可以增加到7個(其中2個是臨時線程)
             * 參數(shù)3:當(dāng)臨時線程對象超出300毫秒的時候還沒有接到新任務(wù),線程池就自動 銷毀臨時的線程對象
             * 參數(shù)4:時間單位。這指定秒,具體參考TimeUnit的枚舉類型
             * 參數(shù)5:等待執(zhí)行的任務(wù)序列4個(其中有4個任務(wù)序列等待線程池對象來執(zhí)行任務(wù))
             */
    
            ThreadPoolExecutor executor = new ThreadPoolExecutor(5,7,300, 
            					TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(4));
    
            for (int i = 0; i < 6; i++) {
                executor.execute(new MyRunnable(i));
                showInfo(executor);
            }
        }
    
    	//獲取線程的一些信息
        private static void showInfo(ThreadPoolExecutor executor) {
            System.out.println("線程池的總數(shù)量:"+executor.getPoolSize());
            System.out.println("隊列中等待執(zhí)行的任務(wù)數(shù):"+executor.getQueue().size());
            System.out.println("已經(jīng)執(zhí)行完畢的任務(wù)數(shù):"+executor.getCompletedTaskCount());
            System.out.println("---------");
        }
    }

    4、Runnable和Callable的區(qū)別:

    Runnable是不返還值的,而Callable可以返回值,具體可以看這篇博客(其實主要我也沒深入學(xué)習(xí)這個哈哈): Runnable和Callable的區(qū)別

    到此,相信大家對“Java多線程是什么及如何創(chuàng)建”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問一下細節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI