JAVA:线程总结及多线程实现的两种方法
JAVA:線程總結
目錄
?
目錄
JAVA:線程總結
JAVA:線程總結
01_多線程(多線程的引入)(了解)
02_多線程(多線程并行和并發的區別)(了解)
03_多線程(Java程序運行原理和JVM的啟動是多線程的嗎)(了解)
04_多線程(多線程程序實現的方式1)(掌握)
05_多線程(多線程程序實現的方式2)(掌握)
06_多線程(實現Runnable的原理)(了解)
07_多線程(兩種方式的區別)(掌握)
08_多線程(匿名內部類實現線程的兩種方式)(掌握)
09_多線程(獲取名字和設置名字)(掌握)
10_多線程(獲取當前線程的對象)(掌握)?
11_多線程(休眠線程)(掌握)
12_多線程(守護線程)(掌握)
13_多線程(加入線程)(掌握)
14_多線程(禮讓線程)(了解)
15_多線程(設置線程的優先級)(了解)
16_多線程(同步代碼塊)(掌握)
17_多線程(同步方法)(掌握)
18_多線程(線程安全問題)(掌握)
19_多線程(火車站賣票的例子用實現Runnable接口)(掌握)
20_多線程(死鎖)(了解)
21_多線程(以前的線程安全的類回顧)(掌握)
22_多線程(Timer)(掌握)
23_多線程(兩個線程間的通信)(掌握)
24_多線程(三個或三個以上間的線程通信)
25_多線程(JDK1.5的新特性互斥鎖)(掌握)
26_多線程(線程組的概述和使用)(了解)
27_多線程(線程的五種狀態)(掌握)
28_多線程(線程池的概述和使用)(了解)
29_多線程(多線程程序實現的方式3)(了解)
?
?
?
?
01_多線程(多線程的引入)(了解) * * 1.什么是線程 * * 線程是程序執行的一條路徑, 一個進程中可以包含多條線程 * * 多線程并發執行可以提高程序的效率, 可以同時完成多項工作 * * 2.多線程的應用場景 * * 紅蜘蛛同時共享屏幕給多個電腦 * * 迅雷開啟多條線程一起下載 * * QQ同時和多個人一起視頻 * * 服務器同時處理多個客戶端請求 * 2_多線程(多線程并行和并發的區別)(了解) * * 并行就是兩個任務同時運行,就是甲任務進行的同時,乙任務也在進行。(需要多核CPU) * * 并發是指兩個任務都請求運行,而處理器只能按受一個任務,就把這兩個任務安排輪流進行,由于時間間隔較短,使人感覺兩個任務都在運行。 * * 比如我跟兩個網友聊天,左手操作一個電腦跟甲聊,同時右手用另一臺電腦跟乙聊天,這就叫并行。 * * 如果用一臺電腦我先給甲發個消息,然后立刻再給乙發消息,然后再跟甲聊,再跟乙聊。這就叫并發。03_多線程(Java程序運行原理和JVM的啟動是多線程的嗎)(了解) * * A:Java程序運行原理 * * Java命令會啟動java虛擬機,啟動JVM,等于啟動了一個應用程序,也就是啟動了一個進程。 * 該進程會自動啟動一個 “主線程” ,然后主線程去調用某個類的 main 方法。 * * * B:JVM的啟動是多線程的嗎 * * JVM啟動至少啟動了垃圾回收線程和主線程,所以是多線程的。 public class testThread1 {public static void main(String []args){for (int i = 0; i <3000000 ; i++) {new Demo();}for (int i = 0; i <3000000 ; i++) {System.out.println("主線程");}} } class Demo{@Overrideprotected void finalize() {System.out.println("垃圾回收成功");} }?
?
04_多線程(多線程程序實現的方式1)(掌握) 多線程兩種實現方式 (1)繼承Thread* 定義類繼承Thread* 重寫run方法* 把新線程要做的事寫在run方法中* 創建線程對象* 開啟新線程, 內部會自動執行run方法 public class testThread2 {public static void main(String []args){Test t=new Test();//t.run(); //run()方法是普通方法,要調用start()方法才會開始線程t.start();for (int i = 0; i <3000000 ; i++) {System.out.println("b");}} } class Test extends Thread{@Overridepublic void run() {for (int i = 0; i <3000000; i++) {System.out.println("a");}} } 05_多線程(多線程程序實現的方式2)(掌握) (2)實現Runnable* 定義類實現Runnable接口* 實現run方法* 把新線程要做的事寫在run方法中* 創建自定義的Runnable的子類對象* 創建Thread對象, 傳入Runnable* 調用start()開啟新線程, 內部會自動調用Runnable的run()方法 public class testThread3 {public static void main(String []args){Test1 t=new Test1();Thread td=new Thread(t);td.start();for (int i = 0; i <3000000 ; i++) {System.out.println("b");}} } class Test1 implements Runnable{@Overridepublic void run() {for (int i = 0; i <300000 ; i++) {System.out.println("a");}} }?
?
06_多線程(實現Runnable的原理)(了解)實現原理:
?? ?繼承Thread?? ?:?? ?由于子類重寫了Thread類的run(), 當調用start()時, 直接找子類的run()方法
?? ?實現Runnable:?? ?構造函數中傳入了Runnable的引用, 成員變量記住了它, start()調用run()方法時內部判斷成員變量Runnable的引用是否為空, 不為空編譯時看的是Runnable的run(),運行時執行的是子類的run()方法
優缺點:
?? ?繼承Thread?? ?:
?? ??? ?好處:?? ?可以直接使用Thread類中的方法,代碼簡單
?? ??? ?弊端:?? ?如果已經有了父類,就不能用這種方法
?? ?實現Runnable:
?? ??? ?好處:?? ?即使自己定義的線程類有了父類也沒關系,因為有了父類也可以實現接口,而且接口是可以多實現的
?? ??? ?弊端:?? ?不能直接使用Thread中的方法需要先獲取到線程對象后,才能得到Thread的方法,代碼復雜
?
?
08_多線程(匿名內部類實現線程的兩種方式)(掌握) public class testThread4 {public static void main(String []args){new Thread(){@Overridepublic void run() {for (int i = 0; i <300000 ; i++) {System.out.println("a");}}}.start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i <3000000 ; i++) {System.out.println("b");}}}){}.start();} }?
?
09_多線程(獲取名字和設置名字)(掌握) * * 1.獲取名字 * * 通過getName()方法獲取線程對象的名字 * * 2.設置名字 * * 通過構造函數可以傳入String類型的名字 public class testThread5 {public static void main(String []args){//demo1();//通過setName()修改namenew Thread(){@Overridepublic void run() {this.setName("楊大大");System.out.println(this.getName()+"a"); //獲取線程名字}}.start();}private static void demo1() {//通過構造方法給name賦值new Thread("楊大大"){@Overridepublic void run() {System.out.println(this.getName()+"a"); //獲取線程名字}}.start();new Thread("恒大大"){@Overridepublic void run() {System.out.println(this.getName()+"b");}}.start();} }?
?
10_多線程(獲取當前線程的對象)(掌握) * * Thread.currentThread(), 主線程也可以獲取 public class testThread6{public static void main(String []args){new Thread("楊大大"){@Overridepublic void run() {System.out.println(this.getName()+"a"); //獲取線程名字}}.start();new Thread(new Runnable(){@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"b");}}){}.start();System.out.println(Thread.currentThread().getName());} }?
?
11_多線程(休眠線程)(掌握) * * Thread.sleep(毫秒,納秒), 控制當前線程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000納秒 1000000000 public class testThread7 {public static void main(String []args) throws InterruptedException {//demo1();new Thread(){@Overridepublic void run() {for (int i = 0; i <10; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("a");}}}.start();new Thread(){@Overridepublic void run() {for (int i = 0; i <10 ; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("b");}}}.start();}private static void demo1() throws InterruptedException {for (int i = 20; i >=0 ; i--) {Thread.sleep(1000);System.out.println("倒計時第"+i+"秒");}} }?
?
12_多線程(守護線程)(掌握) * * setDaemon(), 設置一個線程為守護線程, 該線程不會單獨執行, 當其他非守護線程都執行結束后, 自動退出 * * public class testThread8 {public static void main(String []args){Thread t1=new Thread(){@Overridepublic void run() {for (int i = 0; i <2 ; i++) {System.out.println(this.getName()+"a");}}};Thread t2=new Thread(){@Overridepublic void run() {for (int i = 0; i <20 ; i++) {System.out.println(this.getName()+"b");}}};t2.setDaemon(true);t1.start();t2.start();} }?
?
13_多線程(加入線程)(掌握) * * join(), 當前線程暫停, 等待指定的線程執行結束后, 當前線程再繼續 * * join(int), 可以等待指定的毫秒之后繼續 public class testThread9 {public static void main(String []args){Thread t1=new Thread(){@Overridepublic void run() {for (int i = 0; i <10 ; i++) {System.out.println(this.getName()+"a");}}};Thread t2=new Thread(){@Overridepublic void run() {for (int i = 0; i <10 ; i++) {if (i==2){try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(this.getName()+"b");}}};t1.start();t2.start();} }?
?
14_多線程(禮讓線程)(了解) * * yield讓出cpu public class testThread10 {public static void main(String []args){new Test2().start();new Test2().start();} } class Test2 extends Thread{@Overridepublic void run() {for (int i = 0; i <1000 ; i++) {if (i%10==0){Thread.yield(); //讓出cpu}System.out.println(this.getName()+"aaa"+i);}} }?
?
15_多線程(設置線程的優先級)(了解) * * setPriority()設置線程的優先級 public class testThread11 {public static void main(String []args){Thread t1=new Thread(){@Overridepublic void run() {for (int i = 0; i <100; i++) {System.out.println(this.getName()+"a");}}};Thread t2=new Thread(){@Overridepublic void run() {for (int i = 0; i <100 ; i++) {System.out.println(this.getName()+"b");}}}; // t1.setPriority(10); //設置最大優先級 // t2.setPriority(1);t1.setPriority(Thread.MIN_PRIORITY);t2.setPriority(Thread.MAX_PRIORITY);t1.start();t2.start();} }?
?
16_多線程(同步代碼塊)(掌握) * * 1.什么情況下需要同步 * * 當多線程并發, 有多段代碼同時執行時, 我們希望某一段代碼執行的過程中CPU不要切換到其他線程工作. 這時就需要同步. * * 如果兩段代碼是同步的, 那么同一時間只能執行一段, 在一段代碼沒執行結束之前, 不會執行另外一段代碼. * * 2.同步代碼塊 * * 使用synchronized關鍵字加上一個鎖對象來定義一段代碼, 這就叫同步代碼塊 * * 多個同步代碼塊如果使用相同的鎖對象, 那么他們就是同步的 public class testThread12 {public static void main(String []args){final Print p=new Print();new Thread(){@Overridepublic void run() {while (true){p.print1();}}}.start();new Thread(){@Overridepublic void run() {while (true){p.print2();}}}.start();} } class Print{test3 t=new test3();public void print1(){//synchronized (new test3())synchronized (t){ //同步代碼塊,鎖機制,鎖對象可以是任意的,不是匿名對象,因為匿名對象地址不一樣System.out.print("傳");System.out.print("智");System.out.print("播");System.out.print("客");System.out.print("\r\n");}}public void print2(){synchronized (t){System.out.print("用");System.out.print("心");System.out.print("創");System.out.print("造");System.out.print("\r\n");}} } class test3{}?
?
17_多線程(同步方法)(掌握) * * 使用synchronized關鍵字修飾一個方法, 該方法中所有的代碼都是同步的 //非靜態的同步方法的鎖對象是什么? //鎖對象是this //靜態的同步方法的鎖對象是什么? //鎖對象是該類的字節碼對象 //同步方法只需要在方法上加synchronized關鍵字即可 //同步代碼塊,鎖機制,鎖對象可以是任意的,不是匿名對象,因為匿名對象地址不一樣 public class testThread13 {public static void main(String []args){final Print p=new Print();new Thread(){@Overridepublic void run() {while (true){p.print1();}}}.start();new Thread(){@Overridepublic void run() {while (true){p.print2();}}}.start();} } class Print1{test3 t=new test3();public synchronized void print1(){ //同步方法只需要在方法上加synchronized關鍵字即可synchronized (t){ //同步代碼塊,鎖機制,鎖對象可以是任意的,不是匿名對象,因為匿名對象地址不一樣System.out.print("傳");System.out.print("智");System.out.print("播");System.out.print("客");System.out.print("\r\n");}}public void print2(){synchronized (t){System.out.print("用");System.out.print("心");System.out.print("創");System.out.print("造");System.out.print("\r\n");}} } class test4{ }?
?
18_多線程(線程安全問題)(掌握) * * 多線程并發操作同一數據時, 就有可能出現線程安全問題 * * 使用同步技術可以解決這種問題, 把操作數據的代碼進行同步, 不要多個線程一起操作 *需求:鐵路售票,一共100張,通過四個窗口賣完. public class test1 {public static void main(String []args){new Ticket().start();new Ticket().start();new Ticket().start();new Ticket().start();} } class Ticket extends Thread{private int ticket=100;@Overridepublic void run() {while (true){synchronized (Ticket.class){if (ticket==0){break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(this.getName()+"這是第"+ticket--+"票");}}} }?
?
19_多線程(火車站賣票的例子用實現Runnable接口)(掌握) public class test2 {public static void main(String []args){MyTicket t=new MyTicket();new Thread(t).start();new Thread(t).start();new Thread(t).start();new Thread(t).start();/*Thread t1=new Thread(t);t1.start();t1.start();t1.start();t1.start();*/ //多次啟動一個線程是非法的} } class MyTicket implements Runnable{private int ticket=100;@Overridepublic void run() {while (true){synchronized (Ticket.class){if (ticket<=0){break;}try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"這是第"+ticket--+"票");}}} }?
?
20_多線程(死鎖)(了解) * * 多線程同步的時候, 如果同步代碼嵌套, 使用相同鎖, 就有可能出現死鎖 * * 盡量不要嵌套使用 public class testThread14 {private static String s1="筷子左";private static String s2="筷子右";public static void main(String []args){new Thread(){@Overridepublic void run() {while (true){synchronized (s1) {System.out.println(this.getName()+"獲取" + s1+"等待"+s2);synchronized (s2){System.out.println(this.getName()+"拿到"+s2+"開吃");}}}}}.start();new Thread(){@Overridepublic void run() {while (true){synchronized (s2) {System.out.println(this.getName()+"獲取" + s2+"等待"+s1);synchronized (s1){System.out.println(this.getName()+"拿到"+s1+"開吃");}}}}}.start();} }?
?
21_多線程(以前的線程安全的類回顧)(掌握) // * A:回顧以前說過的線程安全問題 // * 看源碼:Vector,StringBuffer,Hashtable,Collections.synchroinzed(xxx) // * Vector是線程安全的,ArrayList是線程不安全的 // * StringBuffer是線程安全的,StringBuilder是線程不安全的 // * Hashtable是線程安全的,HashMap是線程不安全的22_多線程(Runtime類)
public class testRunTime1 {public static void main(String []args) throws IOException {Runtime r=Runtime.getRuntime();r.exec("shutdown -s -t 300");r.exec("shutdown -a");} }23_多線程(Timer)(掌握)
public class testTimer1 {public static void main(String []args) throws InterruptedException {Timer t=new Timer();t.schedule(new MyTimerTask(),new Date(188,1,14,14,46,1),1);while (true){Thread.sleep(1000);System.out.println(new Date());}} } class MyTimerTask extends TimerTask{@Overridepublic void run() {System.out.println("起床");} }24_多線程(兩個線程間的通信)(掌握)
* 1.什么時候需要通信* 多個線程并發執行時, 在默認情況下CPU是隨機切換線程的* 如果我們希望他們有規律的執行, 就可以使用通信, 例如每個線程執行一次打印 * 2.怎么通信* 如果希望線程等待, 就調用wait()* 如果希望喚醒等待的線程, 就調用notify();* 這兩個方法必須在同步代碼中執行, 并且使用同步鎖對象來調用 public class testNotify1 {public static void main(String []args){final Print p=new Print();new Thread(){@Overridepublic void run() {while (true){try {p.print1();} catch (InterruptedException e) {e.printStackTrace();}}}}.start();new Thread(){@Overridepublic void run() {while (true){try {p.print2();} catch (InterruptedException e) {e.printStackTrace();}}}}.start();} }class Print {private int flag=1;public void print1() throws InterruptedException {synchronized (this){if (flag!=1){this.wait();}System.out.print("傳");System.out.print("智");System.out.print("播");System.out.print("客");System.out.println("\r\n");flag=2;this.notify(); //隨機喚醒單個等待線程}}public void print2() throws InterruptedException {synchronized (this){if (flag!=2){this.wait();}System.out.print("黑");System.out.print("馬");System.out.print("程");System.out.print("序");System.out.println("\r\n");flag=1;this.notify();}} }25_多線程(三個或三個以上間的線程通信)
* 多個線程通信的問題* notify()方法是隨機喚醒一個線程* notifyAll()方法是喚醒所有線程* JDK5之前無法喚醒指定的一個線程* 如果多個線程之間通信, 需要使用notifyAll()通知所有線程, 用while來反復判斷條件 1.在同步代碼塊中,用哪個對象所=鎖就用哪個對象調用weit方法 *2.為什么wait和notify方法定義在Object? * 因為鎖對象可以是任意的 * 3.sleep方法和wait方法的區別? * sleep方法必須傳入參數,參數是時間,時間到了會自動醒來 * wait方法可以傳入參數也可以不傳入參數,傳入參數就是在參數的時間結束后等待v,不傳入參數就是直接等待 *sleep方法在同步函數或同步代碼塊中不釋放鎖 * wait方法在同步函數或同步代碼塊中釋放鎖 public class testNotify2 {public static void main(String []args){final Print2 p=new Print2();new Thread(){@Overridepublic void run() {while (true){try {p.print1();} catch (InterruptedException e) {e.printStackTrace();}}}};new Thread(){@Overridepublic void run() {while (true){try {p.print2();} catch (InterruptedException e) {e.printStackTrace();}}}};new Thread(){@Overridepublic void run() {while (true){try {p.print3();} catch (InterruptedException e) {e.printStackTrace();}}}};} } class Print2 {private int flag=1;public void print1() throws InterruptedException {synchronized (this){while (flag!=1){this.wait();}System.out.print("傳");System.out.print("智");System.out.print("播");System.out.print("客");System.out.println("\r\n");flag=2;//this.notify(); //隨機喚醒單個等待線程this.notifyAll();}}public void print2() throws InterruptedException {synchronized (this){while (flag!=2){this.wait();}System.out.print("黑");System.out.print("馬");System.out.print("程");System.out.print("序");System.out.println("\r\n");flag=3;//this.notify();this.notifyAll();}}public void print3() throws InterruptedException {synchronized (this) {while (flag != 3) { //線程3在此等待,if在哪里等待,就在哪里起來this.wait();} //while循環是循環判斷,每次都會判斷System.out.print("i");System.out.print("t");System.out.print("hei");System.out.print("ma");System.out.println("\r\n");flag = 1;//this.notify();this.notifyAll();}} }26_多線程(JDK1.5的新特性互斥鎖)(掌握)
* 1.同步* 使用ReentrantLock類的lock()和unlock()方法進行同步 * 2.通信* 使用ReentrantLock類的newCondition()方法可以獲取Condition對象* 需要等待的時候使用Condition的await()方法, 喚醒的時候用signal()方法* 不同的線程使用不同的Condition, 這樣就能區分喚醒的時候找哪個線程了 public class testLock1 {public static void main(String []args){Print3 p=new Print3();new Thread(){@Overridepublic void run() {try {p.print1();} catch (InterruptedException e) {e.printStackTrace();}}}.start();new Thread(){@Overridepublic void run() {try {p.print2();} catch (InterruptedException e) {e.printStackTrace();}}}.start();new Thread(){@Overridepublic void run() {try {p.print3();} catch (InterruptedException e) {e.printStackTrace();}}}.start();} } class Print3 {private ReentrantLock r=new ReentrantLock();private Condition c1=r.newCondition();private Condition c2=r.newCondition();private Condition c3=r.newCondition();private int flag=1;public void print1() throws InterruptedException{r.lock();if (flag!=1){c1.await();}System.out.print("傳");System.out.print("智");System.out.print("播");System.out.print("客");System.out.println("\r\n");flag=2;//this.notify(); //隨機喚醒單個等待線程c2.signal();r.unlock();}public void print2() throws InterruptedException {r.lock();if (flag!=2){c2.await();}System.out.print("黑");System.out.print("馬");System.out.print("程");System.out.print("序");System.out.println("\r\n");flag=3;//this.notify();c3.signal();r.unlock();}public void print3() throws InterruptedException {r.lock();if (flag != 3) { //線程3在此等待,if在哪里等待,就在哪里起來c3.await();} //while循環是循環判斷,每次都會判斷System.out.print("i");System.out.print("t");System.out.print("hei");System.out.print("ma");System.out.println("\r\n");flag = 1;//this.notify();c1.signal();r.unlock();} }27_多線程(線程組的概述和使用)(了解)
* A:線程組概述* Java中使用ThreadGroup來表示線程組,它可以對一批線程進行分類管理,Java允許程序直接對線程組進行控制。* 默認情況下,所有的線程都屬于主線程組。* public final ThreadGroup getThreadGroup()//通過線程對象獲取他所屬于的組* public final String getName()//通過線程組對象獲取他組的名字* 我們也可以給線程設置分組* 1,ThreadGroup(String name) 創建線程組對象并給其賦值名字* 2,創建線程對象* 3,Thread(ThreadGroup?group, Runnable?target, String?name) * 4,設置整組的優先級或者守護線程* B:案例演示* 線程組的使用,默認是主線程組 public class testThreadGroup1 {public static void main(String []args){//demo1();ThreadGroup tg=new ThreadGroup("我是一個新的線程組"); //創建新的線程組MyRunnable mr=new MyRunnable();Thread t1=new Thread(tg,mr,"張三");Thread t2=new Thread(tg,mr,"李四");System.out.println(t1.getThreadGroup().getName());System.out.println(t2.getThreadGroup().getName());}private static void demo1() {MyRunnable mr=new MyRunnable();Thread t1=new Thread(mr,"張三");Thread t2=new Thread(mr,"李四");ThreadGroup tg1=t1.getThreadGroup();ThreadGroup tg2=t2.getThreadGroup();System.out.println(tg1.getName());System.out.println(tg2.getName());} } class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i <1000 ; i++) {System.out.println(Thread.currentThread().getName()+"a"+i);}} }28_多線程(線程的五種狀態)(掌握)
29_多線程(線程池的概述和使用)(了解)
* A:線程池概述* 程序啟動一個新線程成本是比較高的,因為它涉及到要與操作系統進行交互。而使用線程池可以很好的提高性能,尤其是當程序中要創建大量生存期很短的線程時,更應該考慮使用線程池。線程池里的每一個線程代碼結束后,并不會死亡,而是再次回到線程池中成為空閑狀態,等待下一個對象來使用。在JDK5之前,我們必須手動實現自己的線程池,從JDK5開始,Java內置支持線程池 * B:內置線程池的使用概述* JDK5新增了一個Executors工廠類來產生線程池,有如下幾個方法* public static ExecutorService newFixedThreadPool(int nThreads)* public static ExecutorService newSingleThreadExecutor()* 這些方法的返回值是ExecutorService對象,該對象表示一個線程池,可以執行Runnable對象或者Callable對象代表的線程。它提供了如下方法* Future<?> submit(Runnable task)* <T> Future<T> submit(Callable<T> task)* 使用步驟:* 創建線程池對象* 創建Runnable實例* 提交Runnable實例* 關閉線程池* C:案例演示 public class testCallable1 {public static void main(String []args) throws ExecutionException, InterruptedException {ExecutorService pool= Executors.newFixedThreadPool(2);Future<Integer> f1=pool.submit(new MyCallable(100)); //將線程放進線程池并執行Future<Integer> f2=pool.submit(new MyCallable(50));System.out.println(f1.get());System.out.println(f2.get());pool.shutdown();} } class MyCallable implements Callable<Integer>{private int num;public MyCallable(int num) {this.num = num;}@Overridepublic Integer call() throws Exception {int sum=0;for (int i = 1; i <=num ; i++) {sum+=1;}return sum;} } 提交的是Callable * * 多線程程序實現的方式3的好處和弊端 * * 好處: * * 可以有返回值 * * 可以拋出異常 * * * 弊端: * * 代碼比較復雜,所以一般不用 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JAVA:线程总结及多线程实现的两种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器开放特定端口的方法
- 下一篇: 8 操作系统第二章 进程管理 信号量