- Java并發(fā)編程之美
- 翟陸續(xù) 薛賓田
- 923字
- 2019-07-25 11:53:59
1.2 線程創(chuàng)建與運(yùn)行
Java中有三種線程創(chuàng)建方式,分別為實(shí)現(xiàn)Runnable接口的run方法,繼承Thread類并重寫run的方法,使用FutureTask方式。
首先看繼承Thread類方式的實(shí)現(xiàn)。
public class ThreadTest { //繼承Thread類并重寫run方法 public static class MyThread extends Thread { @Override public void run() { System.out.println("I am a child thread"); }
} public static void main(String[] args) { // 創(chuàng)建線程 MyThread thread = new MyThread(); // 啟動(dòng)線程 thread.start(); } }
如上代碼中的MyThread類繼承了Thread類,并重寫了run()方法。在main函數(shù)里面創(chuàng)建了一個(gè)MyThread的實(shí)例,然后調(diào)用該實(shí)例的start方法啟動(dòng)了線程。需要注意的是,當(dāng)創(chuàng)建完thread對(duì)象后該線程并沒有被啟動(dòng)執(zhí)行,直到調(diào)用了start方法后才真正啟動(dòng)了線程。
其實(shí)調(diào)用start方法后線程并沒有馬上執(zhí)行而是處于就緒狀態(tài),這個(gè)就緒狀態(tài)是指該線程已經(jīng)獲取了除CPU資源外的其他資源,等待獲取CPU資源后才會(huì)真正處于運(yùn)行狀態(tài)。一旦run方法執(zhí)行完畢,該線程就處于終止?fàn)顟B(tài)。
使用繼承方式的好處是,在run()方法內(nèi)獲取當(dāng)前線程直接使用this就可以了,無須使用Thread.currentThread()方法;不好的地方是Java不支持多繼承,如果繼承了Thread類,那么就不能再繼承其他類。另外任務(wù)與代碼沒有分離,當(dāng)多個(gè)線程執(zhí)行一樣的任務(wù)時(shí)需要多份任務(wù)代碼,而Runable則沒有這個(gè)限制。下面看實(shí)現(xiàn)Runnable接口的run方法方式。
public static class RunableTask implements Runnable{ @Override public void run() { System.out.println("I am a child thread"); } } public static void main(String[] args) throws InterruptedException{ RunableTask task = new RunableTask(); new Thread(task).start(); new Thread(task).start(); }
如上面代碼所示,兩個(gè)線程共用一個(gè)task代碼邏輯,如果需要,可以給RunableTask添加參數(shù)進(jìn)行任務(wù)區(qū)分。另外,RunableTask可以繼承其他類。但是上面介紹的兩種方式都有一個(gè)缺點(diǎn),就是任務(wù)沒有返回值。下面看最后一種,即使用FutureTask的方式。
//創(chuàng)建任務(wù)類,類似Runable public static class CallerTask implements Callable<String>{ @Override public String call() throws Exception { return "hello"; } } public static void main(String[] args) throws InterruptedException { // 創(chuàng)建異步任務(wù) FutureTask<String> futureTask = new FutureTask<>(new CallerTask()); //啟動(dòng)線程 new Thread(futureTask).start(); try { //等待任務(wù)執(zhí)行完畢,并返回結(jié)果 String result = futureTask.get(); System.out.println(result); } catch (ExecutionException e) { e.printStackTrace(); } }
如上代碼中的CallerTask類實(shí)現(xiàn)了Callable接口的call()方法。在main函數(shù)內(nèi)首先創(chuàng)建了一個(gè)FutrueTask對(duì)象(構(gòu)造函數(shù)為CallerTask的實(shí)例),然后使用創(chuàng)建的FutrueTask對(duì)象作為任務(wù)創(chuàng)建了一個(gè)線程并且啟動(dòng)它,最后通過futureTask.get()等待任務(wù)執(zhí)行完畢并返回結(jié)果。
小結(jié):使用繼承方式的好處是方便傳參,你可以在子類里面添加成員變量,通過set方法設(shè)置參數(shù)或者通過構(gòu)造函數(shù)進(jìn)行傳遞,而如果使用Runnable方式,則只能使用主線程里面被聲明為final的變量。不好的地方是Java不支持多繼承,如果繼承了Thread類,那么子類不能再繼承其他類,而Runable則沒有這個(gè)限制。前兩種方式都沒辦法拿到任務(wù)的返回結(jié)果,但是Futuretask方式可以。
- Node.js+Webpack開發(fā)實(shí)戰(zhàn)
- Design Principles for Process:driven Architectures Using Oracle BPM and SOA Suite 12c
- Python for Secret Agents:Volume II
- Python從小白到大牛
- Python數(shù)據(jù)可視化:基于Bokeh的可視化繪圖
- 算法基礎(chǔ):打開程序設(shè)計(jì)之門
- DevOps入門與實(shí)踐
- 名師講壇:Java微服務(wù)架構(gòu)實(shí)戰(zhàn)(SpringBoot+SpringCloud+Docker+RabbitMQ)
- Learning Vaadin 7(Second Edition)
- Learning Unity 2D Game Development by Example
- Swift 4 Protocol-Oriented Programming(Third Edition)
- Visualforce Developer’s guide
- jQuery for Designers Beginner's Guide Second Edition
- Instant GLEW
- MySQL數(shù)據(jù)庫教程(視頻指導(dǎo)版)