Java——多線程實現的三種方式

創建新執行線程有三種方法。

第一種方法是將類聲明為 Thread 的子類。該子類應重寫 Thread 類的 run 方法。接下來可以分配并啟動該子類的實例。

例如,計算大于某一規定值的質數的線程可以寫成:

class PrimeThread extends Thread {long minPrime;PrimeThread(long minPrime) {this.minPrime = minPrime;}public void run() {// compute primes larger than minPrime. . .}}

然后,下列代碼會創建并啟動一個線程:

     PrimeThread p = new PrimeThread(143);p.start();
1,繼承Thread
定義類繼承Thread
重寫run方法
把新線程要做的事寫到run方法中
創建線程對象
開啟新線程,內部會自動執行run方法

具體的多線程實現代碼如下:

package com.yy.thread;public class Demo2_Thread {
/*** 創建新執行線程有兩種方法。* 一種方法是* ①將類聲明為 Thread 的子類。* ②該子類應重寫 Thread 類的 run 方法。* ③接下來可以分配并啟動該子類的實例。* */public static void main(String[] args) {//開啟一條線程Mythread mt = new Mythread();           //4,創建線程(Thread類)的子類對象mt.start();                             //5,開啟線程,需要一定的時間,所以說,JVM會先執行for循環語句,也就是,會先輸出bb,之后再輸出aaaaaaa;然后再相互交替輸出//public void start() : 使該線程開始執行;Java 虛擬機調用該線程的 run 方法。
//      mt.run();                               //如果這樣調用,只是調用了run方法,執行run方法里面的for循環,線程還是主線程這一個線程,不會出現交替的多線程形式//主線程for (int i = 0; i < 100; i++) {         //為了便于觀察多線程的執行,在主方法里面進行for循環System.out.println("bb");           //這個for循環就是主線程的,兩條線程開啟多線程便于觀察}//兩條線程相互交替進行,即多線程實現}}
class Mythread extends Thread{                  //1,繼承Threadpublic void run(){                          //2,重寫run方法for (int i = 0; i < 100; i++) {         //3,將要執行的代碼寫到run方法中System.out.println("aaaaaaa");  }}
}

創建線程的第二種方法是聲明實現 Runnable 接口的類。該類然后實現 run 方法。

然后可以分配該類的實例,在創建 Thread 時作為一個參數來傳遞并啟動。

采用這種風格的同一個例子如下所示:

     class PrimeRun implements Runnable {long minPrime;PrimeRun(long minPrime) {this.minPrime = minPrime;}public void run() {// compute primes larger than minPrime. . .}}

然后,下列代碼會創建并啟動一個線程:
每個線程都有一個標識名,多個線程可以同名。如果線程創建時沒有指定標識名,就會為其生成一個新名稱。

     PrimeRun p = new PrimeRun(143);new Thread(p).start();
2,實現Runnable
定義類實現Runnable接口
實現run方法
把新線程要做的事先到run方法中
創建自定義的Runnable子類對象
創建Tread對象,傳入Runnable
調用start()開啟新線程,內部會自動調用Runnable的run()方法

具體的多線程實現代碼如下:

package com.yy.thread;public class Demo3_Thread {
/*** 創建線程的另一種方法是* ①聲明實現 Runnable 接口的類。* ②該類然后實現 run 方法。* ③然后可以分配該類的實例,在創建 Thread 時作為一個參數來傳遞并啟動。* * Runnable里面只有一個run()方法,實現Runnable只需要重寫run()方法即可* * * 實現Runnable的原理* 查看源碼:*      1,看Thread類的構造函數,傳遞了Runnable接口的引用*      2,通過init()方法找到傳遞的target給成員變量的target賦值*      3,查看run方法,發現run方法中有判斷,如果target不為null就會調用Runnable接口子類對象的run方法* */public static void main(String[] args) {MyRunnable wsq = new MyRunnable();                  //4,創建Runnable的子類對象
//      Runnable target = wsq;                              //父類引用指向子類對象,new MyRunnable()這個是子類對象也就是wsq  Thread yy = new Thread(wsq);                        //5,將其當作參數傳遞給Thread的構造函數; wsq代表Runnable的子類對象yy.start();                                         //6,開啟線程; Thread里面才有start()方法//      new Thread(wsq).start();                            //這種方法與上面的兩行代碼實現的做用一樣for (int i = 0; i < 100; i++) {System.out.println("你,陪我步入蟬夏,越過城市喧囂,歌聲還在游走,你榴花般的笑容");}}
}
class MyRunnable implements Runnable {                      //1,定義一個類,實現Runnable方法@Override   public void run() {                                     //2,重寫run方法for (int i = 0; i < 100; i++) {                     //3,將要執行的代碼寫到run方法中System.out.println("我真的好想你,在每一個雨季。");           }}   
}

兩種方法的區別:

  • a.繼承Thread : 由于子類重寫了Thread類的run(),當調用start()時,直接找子類的run()方法
  • b.實現Runnable : 構造函數中傳入了Runnable的引用,成員變量記住了它,start()調用run()方法時內部判斷成員變量Runnable的引用是否為空,不為空,編譯時看的是Runnable的run(),運行時執行的時子類的run()方法

繼承Thread(開發中優先考慮)

  • 好處:可以直接使用Thread類中的方法,代碼簡單

  • 弊端:如果已經有了父類,就不能有這個方法,因為java是單繼承的

實現Runnable接口(實際上是對繼承Thread的補充)

  • 好處:即使自己定義的線程類有了父類也沒關系,因為有了父類也可以實現接口,接口是可以多實現的,拓展性強

  • 弊端:不能直接使用Thread中的方法,需要先獲取到線程對象后,才能得到Thread的方法,代碼復雜

第三種方法是創建類是實現Callable這個接口。然后該類重寫 Callable這個接口里的抽象方法call。

Callable 接口類似于 Runnable,兩者都是為那些其實例可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,并且無法拋出經過檢查的異常。

案例:通過實現Callable這個接口,來實現多線程,創建一個求和類;

具體的多線程實現代碼如下:


package com.yy.thread;import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class Demo6_Callable {
/*** 第三種線程創建方式* <T> Future<T> submit(Callable<T> task)* 提交一個返回值的任務用于執行,返回一個表示任務的未決結果的 Future。* 該 Future 的 get 方法在成功完成時將會返回該任務的結果。 * Callable 接口類似于 Runnable,兩者都是為那些其實例可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,并且無法拋出經過檢查的異常。* * */public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService pool  = Executors.newFixedThreadPool(2);    //創建線程池,線程池里面可以養兩個線程Future<Integer> f1 = pool.submit(new MyCallable(100));      //由于下面創建的類中里面有一個有參構造方法,這里得傳一個參數Future<Integer> f2 = pool.submit(new MyCallable(50));//submit返回一個Future,所以說,應該用Future去接收//Future可以獲取出來1-100或者是1-50的求和結果System.out.println(f1.get());System.out.println(f2.get());//V get()   throws InterruptedException,ExecutionException如有必要,等待計算完成,然后獲取其結果。 pool.shutdown();                                            //關閉線程池}}
class MyCallable implements Callable<Integer>{                      //創建一個MyCallable類去實現Callable這個接口private int num;                                                //設置一個成員變量numpublic MyCallable (int num){                                    //創建一個有參構造方法this.num = num;                                             //num是傳進去的數}@Overridepublic Integer call() throws Exception {                        //重寫Callable這個接口里面的抽象方法call;這里的返回值類跟泛型<Integer>是一致的int sum = 0;                                                //實現求和代碼for (int i = 1; i <= num; i++) {sum += i;}return sum;                                                 //返回sum}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379966.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379966.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379966.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python網絡編程---TCP客戶端

0x01 環境 python2、 pycharm 0x02 程序 # -*- coding:UTF-8 -*- import sockettarget_hostwww.baidu.com tarfet_port80target_hostlocalhost target_port3345 dataABCDEF# 創建一個socket對象 client socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 連接客戶端 clien…

c#枚舉數字轉枚舉_C#枚舉能力問題和解答 套裝4

c#枚舉數字轉枚舉1) What is the correct output of given code snippets in C#.NET? using System;class program{enum emp_salary : int{emp1 10000,emp2 15000,emp4 20000}static void Main(string[] args){int sal (int)emp_salary.emp2;Console.WriteLine(sal);}}100…

Java——匿名內部類實現線程的兩種方式

package com.yy.thread;public class Demo4_Thread {public static void main(String[] args) {demo1(); //匿名內部類&#xff0c;第一種&#xff0c;繼承Threaddemo2(); //匿名內部類&#xff0c;第二種&#xff0c;實現Runnable接口 }private static void…

zlib1.2.5的編譯

zlib1.2.5沒有了1.2.4的vc6工程&#xff0c;只好使用命令行編譯。通過win32/Makefile.msc發現有4種編譯方式&#xff0c;如下&#xff1a;# Usage:# nmake -f win32/Makefile.msc (standard build)# nmake -f win32/Makefile.msc LOC-DFOO …

python網絡編程--UDP客戶端

0x01 環境 python、pycharm 0x02 程序 # -*- coding:utf-8 -*-import sockettarget_host127.0.0.1 target_part80#創建一個socket對象 client socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#發送一些數據 client.sendto(AAAAAA,(target_host,target_part))#接收到的消息 …

window.open參數和技巧

【1、最基本的彈出窗口代碼】 <SCRIPT LANGUAGE"javascript"> <!-- window.open (page.html) --> </SCRIPT> 因為著是一段javascripts代碼&#xff0c;所以它們應該放在<SCRIPT LANGUAGE"javascript">標簽和</script>之間。…

java jar包示例_Java包getImplementationTitle()方法和示例

java jar包示例包類的getImplementationTitle()方法 (Package Class getImplementationTitle() method) getImplementationTitle() method is available in java.lang package. getImplementationTitle()方法在java.lang包中可用。 getImplementationTitle() method is used to…

Java——獲取和設置多線程的名稱

給名字進行賦值有兩種方式&#xff1a; 1&#xff0c;通過構造去賦值 Thread(String name) 直接在構造方法里面傳一個名字就行了2&#xff0c;通過set設置的方法進行賦值 package com.yy.threadmethod;public class Demo1_Name {public static void main(String[] args) {dem…

十三、oracle 數據字典和動態性能視圖

一、概念數據字典是oracle數據庫中最重要的組成部分&#xff0c;它提供了數據庫的一些系統信息。動態性能視圖記載了例程啟動后的相關信息。 二、數據字典1)、數據字典記錄了數據庫的系統信息&#xff0c;它是只讀表和視圖的集合&#xff0c;數據字典的所有者為sys用戶。2)、用…

python網絡編程---TCP服務器

0x01 環境 python2 pycharm 0x02 程序 客戶端程序&#xff1a; # -*- coding:UTF-8 -*- import sockettarget_hostwww.baidu.com target_port80target_hostlocalhost target_port3345 dataABCDEF# 創建一個socket對象 client socket.socket(socket.AF_INET,socket.SOCK_STRE…

C# 獲取磁盤容量

/// 獲取指定驅動器的空間總大小(單位為B) /// </summary> /// <param name"str_HardDiskName">只需輸入代表驅動器的字母即可 </param> /// <returns> </returns> public static long GetHardDi…

Java——獲取當前線程的對象(currentThread())(兩種方式)

package com.yy.threadmethod;public class Demo2_CurrentThread { /*** public static Thread currentThread()返回對當前正在執行的線程對象的引用。 * 返回&#xff1a;當前執行的線程。返回的是一個Thread* 該方法主要是為了協助 實現通過Runnable接口來對線程進行設置…

HDU2501_多米諾骨牌

題目大意&#xff1a; 有一個大小是 2 x n 的網格&#xff0c;現在需要用2種規格的骨牌鋪滿&#xff0c;骨牌規格分別是 2 x 1 和 2 x 2&#xff0c;請計算一共有多少種鋪設的方法。 解題思路&#xff1a; 找出遞推公式&#xff1a; f[i] f[i-1] f[i-2] * 2; 代碼&#xff1a…

java jar包示例_Java包getSpecificationVendor()方法和示例

java jar包示例包類的getSpecificationVendor()方法 (Package Class getSpecificationVendor() method) getSpecificationVendor() method is available in java.lang package. getSpecificationVendor()方法在java.lang包中可用。 getSpecificationVendor() method is used to…

sys.argv和getopt

0x01 sys.argv sys.argv用來讀取命令行參數&#xff0c;保存程序的文件名和命令參數&#xff0c;讀入的參數以列表保存 import sysprint sys.argv print type(sys.argv)可以看到&#xff0c;sys.argv把空格當成分隔符&#xff0c;空格兩邊的值當做sys.argv的一個元素&#xf…

[導入]《大話設計模式》重印公告

摘要: 《大話設計模式》12月中旬上市&#xff0c;至2008年1月底僅僅一個多月&#xff0c;5000冊即銷售一空&#xff0c;清華大學出版社已經開始重印&#xff0c;也就是說很快可以在二月底或三月初看到新印刷修正過大部分錯誤的《大話設計模式》。 閱讀全文[新聞]《人民日報市場…

Java——線程的四種不同形式

一&#xff0c;休眠線程 public static void sleep(long millis) throws InterruptedException 在指定的毫秒數內讓當前正在執行的線程休眠&#xff08;暫停執行&#xff09;&#xff0c;此操作受到系統計時器和調度程序精度和準確性的影響。該線程不丟失任何監視器的所屬權。…

hdu1053 Entropy hdu2527 Safe Or Unsafe

裸裸的哈弗曼編碼&#xff0c;求出哈弗曼編碼的路徑長度&#xff0c;注意整個字符串為一種字符的情況 View Code #include<iostream>#include<queue>#include<algorithm>#include<vector>using namespace std;struct node{int u,w; node(int a0,in…

Java ListResourceBundle getContents()方法與示例

ListResourceBundle類的getContents()方法 (ListResourceBundle Class getContents() method) getContents() method is available in java.util package. getContents()方法在java.util包中可用。 getContents() method is used to get the contents into the form of an Obje…

DOM元素的所有子元素 .elements

.elements屬性用來獲取某個DOM元素的所有子元素&#xff0c;是個很有用的屬性&#xff0c;可用于用className來獲取指定元素等用途。 轉載于:https://www.cnblogs.com/cly84920/archive/2008/08/06/4427136.html