自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

死磕 Java線程系列之創(chuàng)建線程的8種方式

開發(fā) 后端
創(chuàng)建線程,是多線程編程中最基本的操作,彤哥總結(jié)了一下,大概有8種創(chuàng)建線程的方式,你知道嗎?

 

簡介

創(chuàng)建線程,是多線程編程中最基本的操作,彤哥總結(jié)了一下,大概有8種創(chuàng)建線程的方式,你知道嗎?

繼承Thread類并重寫run()方法

 

  1. public class CreatingThread01 extends Thread {  
  2.     @Override  
  3.     public void run() {  
  4.         System.out.println(getName() + " is running");  
  5.     }  
  6.     public static void main(String[] args) {  
  7.         new CreatingThread01().start();  
  8.         new CreatingThread01().start();  
  9.         new CreatingThread01().start();  
  10.         new CreatingThread01().start();  
  11.     }  

繼承Thread類并重寫run()方法,這種方式的弊端是一個(gè)類只能繼承一個(gè)父類,如果這個(gè)類本身已經(jīng)繼承了其它類,就不能使用這種方式了。

實(shí)現(xiàn)Runnable接口

 

  1. public class CreatingThread02 implements Runnable {  
  2.     @Override  
  3.     public void run() {  
  4.         System.out.println(Thread.currentThread().getName() + " is running");  
  5.     }  
  6.     public static void main(String[] args) {  
  7.         new Thread(new CreatingThread02()).start();  
  8.         new Thread(new CreatingThread02()).start();  
  9.         new Thread(new CreatingThread02()).start();  
  10.         new Thread(new CreatingThread02()).start();  
  11.     }  

實(shí)現(xiàn)Runnable接口,這種方式的好處是一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,不影響其繼承體系。

匿名內(nèi)部類

 

  1. public class CreatingThread03 {  
  2.     public static void main(String[] args) {  
  3.         // Thread匿名類,重寫Thread的run()方法  
  4.         new Thread() {  
  5.             @Override  
  6.             public void run() {  
  7.                 System.out.println(getName() + " is running");  
  8.             }  
  9.         }.start();  
  10.         // Runnable匿名類,實(shí)現(xiàn)其run()方法  
  11.         new Thread(new Runnable() {  
  12.             @Override  
  13.             public void run() {  
  14.                 System.out.println(Thread.currentThread().getName() + " is running");  
  15.             }  
  16.         }).start();       
  17.         // 同上,使用lambda表達(dá)式函數(shù)式編程  
  18.         new Thread(()-> 
  19.             System.out.println(Thread.currentThread().getName() + " is running");  
  20.         }).start();  
  21.     }  

使用匿名類的方式,一是重寫Thread的run()方法,二是傳入Runnable的匿名類,三是使用lambda方式,現(xiàn)在一般使用第三種(java8+),簡單快捷。

實(shí)現(xiàn)Callabe接口

 

  1. public class CreatingThread04 implements Callable<long> {  
  2.     @Override  
  3.     public Long call() throws Exception {  
  4.         Thread.sleep(2000);  
  5.         System.out.println(Thread.currentThread().getId() + " is running");  
  6.         return Thread.currentThread().getId();  
  7.     }  
  8.     public static void main(String[] args) throws ExecutionException, InterruptedException {  
  9.         FutureTask<long> task = new FutureTask&lt;&gt;(new CreatingThread04());  
  10.         new Thread(task).start();  
  11.         System.out.println("等待完成任務(wù)");  
  12.         Long result = task.get();  
  13.         System.out.println("任務(wù)結(jié)果:" + result);  
  14.     }  

實(shí)現(xiàn)Callabe接口,可以獲取線程執(zhí)行的結(jié)果,F(xiàn)utureTask實(shí)際上實(shí)現(xiàn)了Runnable接口。

定時(shí)器(java.util.Timer)

 

  1. public class CreatingThread05 {  
  2.     public static void main(String[] args) {  
  3.         Timer timer = new Timer();  
  4.         // 每隔1秒執(zhí)行一次  
  5.         timer.schedule(new TimerTask() {  
  6.             @Override  
  7.             public void run() {  
  8.                 System.out.println(Thread.currentThread().getName() + " is running");  
  9.             }  
  10.         }, 0 , 1000);  
  11.     }  

使用定時(shí)器java.util.Timer可以快速地實(shí)現(xiàn)定時(shí)任務(wù),TimerTask實(shí)際上實(shí)現(xiàn)了Runnable接口。

線程池

 

  1. public class CreatingThread06 {  
  2.     public static void main(String[] args) {  
  3.         ExecutorService threadPool = Executors.newFixedThreadPool(5);  
  4.         for (int i = 0; i &lt; 100; i++) {  
  5.             threadPool.execute(()-&gt; System.out.println(Thread.currentThread().getName() + " is running"));  
  6.         }  
  7.     }  

使用線程池的方式,可以復(fù)用線程,節(jié)約系統(tǒng)資源。

并行計(jì)算(Java8+)

 

  1. public class CreatingThread07 {  
  2.     public static void main(String[] args) {  
  3.         List<integer> list = Arrays.asList(1, 2, 3, 4, 5);  
  4.         // 串行,打印結(jié)果為12345  
  5.         list.stream().forEach(System.out::print);  
  6.         System.out.println();  
  7.         // 并行,打印結(jié)果隨機(jī),比如35214  
  8.         list.parallelStream().forEach(System.out::print);  
  9.     }  

使用并行計(jì)算的方式,可以提高程序運(yùn)行的效率,多線程并行執(zhí)行。

Spring異步方法

首先,springboot啟動(dòng)類加上@EnableAsync注解(@EnableAsync是spring支持的,這里方便舉例使用springboot)。

 

  1. @SpringBootApplication  
  2. @EnableAsync  
  3. public class Application {  
  4.     public static void main(String[] args) {  
  5.         SpringApplication.run(Application.class, args);  
  6.     }  

其次,方法加上@Async注解。

 

  1. @Service  
  2. public class CreatingThread08Service {  
  3.     @Async  
  4.     public void call() {  
  5.         System.out.println(Thread.currentThread().getName() + " is running");  
  6.     }  

然后,測試用例直接跟使用一般的Service方法一模一樣。

 

  1. @RunWith(SpringRunner.class)  
  2. @SpringBootTest(classes = Application.class)  
  3. public class CreatingThread08Test {  
  4.     @Autowired  
  5.     private CreatingThread08Service creatingThread08Service;  
  6.     @Test  
  7.     public void test() {  
  8.         creatingThread08Service.call();  
  9.         creatingThread08Service.call();  
  10.         creatingThread08Service.call();  
  11.         creatingThread08Service.call();  
  12.     }  

運(yùn)行結(jié)果如下:

 

  1. task-3 is running  
  2. task-2 is running  
  3. task-1 is running  
  4. task-4 is running 

可以看到每次執(zhí)行方法時(shí)使用的線程都不一樣。

使用Spring異步方法的方式,可以說是相當(dāng)?shù)胤奖?,適用于前后邏輯不相關(guān)聯(lián)的適合用異步調(diào)用的一些方法,比如發(fā)送短信的功能。

總結(jié)

(1)繼承Thread類并重寫run()方法;

(2)實(shí)現(xiàn)Runnable接口;

(3)匿名內(nèi)部類;

(4)實(shí)現(xiàn)Callabe接口;

(5)定時(shí)器(java.util.Timer);

(6)線程池;

(7)并行計(jì)算(Java8+);

(8)Spring異步方法;

彩蛋

上面介紹了那么多創(chuàng)建線程的方式,其實(shí)本質(zhì)上就兩種,一種是繼承Thread類并重寫其run()方法,一種是實(shí)現(xiàn)Runnable接口的run()方法,那么它們之間到底有什么聯(lián)系呢?

請看下面的例子,同時(shí)繼承Thread并實(shí)現(xiàn)Runnable接口,應(yīng)該輸出什么呢?

 

  1. public class CreatingThread09 {  
  2.     public static void main(String[] args) {  
  3.         new Thread(()-&gt; {  
  4.             System.out.println("Runnable: " + Thread.currentThread().getName());  
  5.         }) {  
  6.             @Override  
  7.             public void run() {  
  8.                 System.out.println("Thread: " + getName());  
  9.             }  
  10.         }.start();  
  11.     }  

說到這里,我們有必要看一下Thread類的源碼:

 

  1. public class Thread implements Runnable {  
  2.     // Thread維護(hù)了一個(gè)Runnable的實(shí)例  
  3.     private Runnable target;     
  4.     public Thread() { 
  5.          init(null, null, "Thread-" + nextThreadNum(), 0);  
  6.     }    
  7.     public Thread(Runnable target) {  
  8.         init(null, target, "Thread-" + nextThreadNum(), 0);  
  9.     }    
  10.     private void init(ThreadGroup g, Runnable target, String name,  
  11.                       long stackSize, AccessControlContext acc,  
  12.                       boolean inheritThreadLocals) {  
  13.         // ...  
  14.         // 構(gòu)造方法傳進(jìn)來的Runnable會(huì)賦值給target  
  15.         this.target = target;  
  16.         // ...  
  17.     }    
  18.     @Override  
  19.     public void run() {  
  20.         // Thread默認(rèn)的run()方法,如果target不為空,會(huì)執(zhí)行target的run()方法  
  21.         if (target != null) {  
  22.             target.run();  
  23.         }  
  24.     }  

看到這里是不是豁然開朗呢?既然上面的例子同時(shí)繼承Thread并實(shí)現(xiàn)了Runnable接口,根據(jù)源碼,實(shí)際上相當(dāng)于重寫了Thread的run()方法,在Thread的run()方法時(shí)實(shí)際上跟target都沒有關(guān)系了。

所以,上面的例子輸出結(jié)果為Thread: Thread-0,只輸出重寫Thread的run()方法中的內(nèi)容。

 

 

責(zé)任編輯:龐桂玉 來源: 中國開源
相關(guān)推薦

2010-03-18 15:31:13

Java創(chuàng)建線程

2023-06-07 13:49:00

多線程編程C#

2018-04-02 14:29:18

Java多線程方式

2020-12-17 05:52:09

線程池ThreadPoolThreadPoolE

2024-11-04 09:39:08

Java?接口Thread?類

2024-02-26 08:28:24

Java線程CPU

2023-06-06 08:17:52

多線程編程Thread類

2017-04-17 19:31:03

Android多線程

2010-03-15 17:56:23

Java多線程

2023-06-08 08:21:08

多線程編程線程間通信

2022-11-02 15:00:03

Java值傳遞引用傳遞

2025-01-14 07:00:00

線程池ExecutorsJava

2019-10-29 19:49:48

Java線程安全

2010-07-14 10:30:26

Perl多線程

2011-06-24 11:03:31

Qt 多線程 線程

2011-06-24 11:12:39

Qt 多線程 線程

2024-02-05 12:08:07

線程方式管理

2023-06-09 07:59:37

多線程編程鎖機(jī)制

2009-03-12 10:52:43

Java線程多線程

2010-02-02 14:32:32

Python線程編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)