這篇文章主要介紹“實現(xiàn)Java線程的方法有哪些”,在日常操作中,相信很多人在實現(xiàn)Java線程的方法有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”實現(xiàn)Java線程的方法有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
成都創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站建設、成都做網(wǎng)站與策劃設計,京口網(wǎng)站建設哪家好?成都創(chuàng)新互聯(lián)做網(wǎng)站,專注于網(wǎng)站建設10余年,網(wǎng)設計領域的專業(yè)建站公司;建站業(yè)務涵蓋:京口等地區(qū)。京口做網(wǎng)站價格咨詢:18982081108
搞懂兩件事: 為什么說本質(zhì)上只有一種實現(xiàn)線程的方式? 實現(xiàn) Runnable 接口究竟比繼承 Thread 類實現(xiàn)線程好在哪里?
public class RunnableThread implements Runnable{ @Override public void run() { System.out.println("用實現(xiàn)Runnable接口實現(xiàn)線程"); } public static void main(String[] args) { Thread thread=new Thread(new RunnableThread()); thread.start(); } }
如代碼所示,首先通過 RunnableThread 類實現(xiàn) Runnable 接口,然后重寫 run() 方法,之后只需要把這個實現(xiàn)了 run() 方法的實例傳到 Thread 類中就可以實現(xiàn)多線程。
public class ExtendsThread extends Thread{ @Override public void run() { System.out.println("用繼承Thread類實現(xiàn)線程"); } }
與第 1 種方式不同的是它沒有實現(xiàn)接口,而是繼承 Thread 類,并重寫了其中的 run() 方法。
下面是線程池中的源碼,來看看線程池是怎么實現(xiàn)線程的:
/** * The default thread factory */ static class DefaultThreadFactory implements ThreadFactory { private static final AtomicInteger poolNumber = new AtomicInteger(1); private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); if (t.isDaemon()) t.setDaemon(false); if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
對于線程池而言,本質(zhì)上是通過線程工廠創(chuàng)建線程的,默認采用 DefaultThreadFactory,它會給線程池創(chuàng)建的線程設置一些默認值,比如:線程的名字、是否是守護線程,以及線程的優(yōu)先級等。但是最終都是通過new Thread()創(chuàng)建線程的,只是參數(shù)多了些而已。
public class CallableTask implements Callable{ @Override public Integer call() throws Exception { return new Random().nextInt(); } public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(10); Future future = executorService.submit(new CallableTask()); System.out.println(future.get()); System.out.println(future.isDone()); System.out.println(future.isCancelled()); } }
Runnable 創(chuàng)建線程是無返回值的,而 Callable 和與之相關的 Future、FutureTask,它們可以把線程執(zhí)行的結(jié)果作為返回值返回,如代碼所示,實現(xiàn)了 Callable 接口,并且給它的泛型設置成 Integer,然后它會返回一個隨機數(shù)。
但是,無論是 Callable 還是 FutureTask,它們首先和 Runnable 一樣,都是一個任務,是需要被執(zhí)行的,而不是說它們本身就是線程。它們可以放到線程池中執(zhí)行,如代碼所示, submit() 方法把任務放到線程池中,并由線程池創(chuàng)建線程,不管用什么方法,最終都是靠線程來執(zhí)行的,而子線程的創(chuàng)建方式仍脫離不了最開始講的兩種基本方式,也就是實現(xiàn) Runnable 接口和繼承 Thread 類。
public static void innerClassThread(){ new Thread(new Runnable() { @Override public void run() { System.out.println("匿名內(nèi)部類創(chuàng)建線程"); } }).start(); } public static void lambdaThread(){ new Thread(()->{ System.out.println("lambda表達式創(chuàng)建線程"); }).start(); }
實際上,匿名內(nèi)部類或 lambda 表達式創(chuàng)建線程,它們僅僅是在語法層面上實現(xiàn)了線程,并不能把它歸結(jié)于實現(xiàn)多線程的方式,如匿名內(nèi)部類實現(xiàn)線程的代碼所示,它僅僅是用一個匿名內(nèi)部類把需要傳入的 Runnable 給實例出來。
了解了上面的幾種創(chuàng)建線程的方式后,我們發(fā)現(xiàn)所有其他創(chuàng)建線程的方式都僅僅是在 new Thread() 外做了一層封裝而已;不同點僅僅在于實現(xiàn)線程運行內(nèi)容的不同。
實現(xiàn)線程執(zhí)行的內(nèi)容,通過實現(xiàn) Runnable 接口的方式
啟動線程需要調(diào)用 start() 方法,而 start() 方法最終還會調(diào)用 run() 方法,Thread中的run()方法源碼如下:
/* What will be run. */ private Runnable target; @Override public void run() { if (target != null) { target.run(); } }
target其實就是一個Runnable,實際線程執(zhí)行的內(nèi)容就是實現(xiàn)了Runnable的接口中的run方法。
實現(xiàn)線程執(zhí)行的內(nèi)容,繼承 Thread 類重寫 run() 方法的方式
啟動線程需要調(diào)用 start() 方法,而 start() 方法最終還會調(diào)用 run() 方法,但是此時的run()方法,因為繼承的原因,此時已被子類重寫了,所以此時線程執(zhí)行的內(nèi)容是子類的run方法。
運行內(nèi)容主要來自于兩個地方,要么來自于 target,要么來自于子類重寫的 run() 方法;因此可以這樣總結(jié):本質(zhì)上,實現(xiàn)線程只有一種方式new Thread(),而要想實現(xiàn)線程執(zhí)行的內(nèi)容,卻有兩種方式,要么通過實現(xiàn) Runnable 接口的方式,要么繼承 Thread 類重寫 run() 方法的方式,把我們想要執(zhí)行的代碼傳入,讓線程去執(zhí)行。
Runnable 里只有一個 run() 方法,它定義了需要執(zhí)行的內(nèi)容,在這種情況下,實現(xiàn)了 Runnable 與 Thread 類的解耦,Thread 類負責線程啟動和屬性設置等內(nèi)容,職責分明。
java單繼承的原因,類一旦繼承了 Thread 類,那么它后續(xù)就沒有辦法再繼承其他的類,限制了代碼未來的可拓展性。
在某些情況下可以提高性能,如果使用繼承 Thread 類方式,每次執(zhí)行一次任務,都需要新建一個獨立的線程;使用實現(xiàn) Runnable 接口的方式,就可以把任務直接傳入線程池,使用一些固定的線程來完成任務,不需要每次新建銷毀線程,大大降低了性能開銷。
到此,關于“實現(xiàn)Java線程的方法有哪些”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
分享標題:實現(xiàn)Java線程的方法有哪些
文章源于:http://weahome.cn/article/pchsge.html