Java核心類庫——執行緒
一:多執行緒技術的概述:
1.直接看截圖:
電腦只能幹一件事情,學習多執行緒的意義在於讓多個路徑更合理的交替執行。CPU的高速切換給我們一種多個執行緒在同時執行的假象。
2.
二:執行緒講解:
1.多執行緒的第一種實現方式:
1.1)該類要實現Tread程序
1.2)程式碼演示:
程序1的類:
1 public class MyThread extends Thread{ 2 @Override 3 public void run() { 4 for(int i = 0;i<10;i++){ 5 System.out.println("汗滴禾下土"+i); 6 } 7 } 8 }
Main()方法:
1 public class Demo01 { 2 public static void main(String[] args) { 3 //建立執行緒物件 4 MyThread thread = new MyThread(); 5 //啟動執行緒 6 thread.start(); 7 for(int i = 0;i<10;i++){ 8 System.out.println("鋤禾日當午"+i); 9 } 10 } 11 }
一下是對上述程式碼的解釋:
由一個執行緒呼叫的方法,該方法也會執行在這個執行緒中
2.執行緒的第二種實現方式:
2.1)實現Runnable()介面
2.2)程式碼演示:
執行緒1:
1 /** 2 * 用於給執行緒執行的任務 3 */ 4 public class MyRunnable implement Runnable{ 5 @Override 6 public void run() { 7 for(int i = 0;i<10;i++){ 8 System.out.println("汗滴禾下土"+i); 9 } 10 } 11 }
主執行緒(Main方法):
1 public class Demo01 { 2 public static void main(String[] args) { 3 //1.建立一個任務物件 4 MyRunnable runnable = new MyRunnable(); 5 //2.建立一個執行緒物件,並給他一個任務 6 Thread t = new Thread(runnable); 7 //3.啟動執行緒 8 t.start(); 9 for(int i = 0;i<10;i++){ 10 System.out.println("鋤禾日當午"+i); 11 } 12 } 13 }
列印的結果同上面相同
3.實現執行緒的兩種方式中,實現Runnable介面的優勢:
雖然Runnable介面很有優勢,但也會使用繼承Thread,因為它可以建立執行緒很方便:
1 public class Demo02 { 2 public static void main(String[] args) { 3 //採用匿名內部類的方式建立執行緒 4 new Thread(){ 5 @Override 6 public void run() { 7 for(int i = 0;i<10;i++){ 8 System.out.println("鋤禾日當午"+i); 9 } 10 } 11 }.start(); 12 for(int i = 0;i<10;i++){ 13 System.out.println("汗滴禾下土"+i); 14 } 15 } 16 }
4.執行緒中常見的方法
1.常見的構造方法
(name是給執行緒起的名字)
2.常用的方法:
2.1)getName();獲取執行緒的名字
2.2) getPriority();獲取執行緒的優先順序
2.3)getStatic();獲取執行緒的狀態
2.4)isAlive();判斷該執行緒是否活著
2.5)isDaemon();判斷該執行緒是否為守護執行緒
2.6)sleep(long millis);讓執行緒休眠多長的時間
2.7)sleep(lont millis,int nanos);
2.8)start();開始執行緒
2.9)
2.10)
3.執行緒技術的程式碼演示:
一:獲取和設定執行緒的名稱:
1 public class Demo02 { 2 public static void main(String[] args) { 3 //首先打印出主程式的名稱 4 System.out.println(Thread.currentThread().getName()); 5 //採用匿名內部類的方式建立一個執行緒 6 new Thread(new MyRunnable(),"誰知盤中餐").start(); 7 8 } 9 //建立一個靜態的內部類 10 static class MyRunnable implements Runnable{ 11 12 @Override 13 public void run() { 14 System.out.println(Thread.currentThread().getName()); 15 } 16 } 17 }
currentThread()獲取當前的執行緒,返回的是一個執行緒
二:執行緒休眠sleep();
1 public class Demo02 { 2 public static void main(String[] args) throws InterruptedException { 3 for(int i = 0;i<10;i++){ 4 System.out.println(i); 5 Thread.sleep(1000); 6 } 7 } 8 }
3.3)執行緒阻塞:可以理解為比較消耗時間的操作,比如一個執行緒要執行100行程式碼,其中有十行程式碼是讀取檔案,這個過程花費了比較多的時間,可以認為是執行緒阻塞。
常見的執行緒阻塞有讀取檔案,等待使用者輸入等
1 public class Demo02 { 2 /** 3 * 需求:我想在Main()方法結束後終端子程式 4 * 1.為子程式打一個標記 5 * 2.在任務類中catch()塊中處理 6 * @param args 7 * @throws InterruptedException 8 */ 9 public static void main(String[] args) throws InterruptedException { 10 Thread t = new Thread(new MyRunnable()); 11 t.start(); 12 for(int i = 0;i<5;i++){ 13 System.out.println(Thread.currentThread().getName()+":"+i); 14 } 15 //1.為子程式打一個標記 16 t.interrupt(); 17 } 18 static class MyRunnable implements Runnable{ 19 20 @Override 21 public void run() { 22 for(int i = 0;i<10;i++){ 23 System.out.println(Thread.currentThread().getName()+":"+i); 24 try { 25 Thread.sleep(1000); 26 } catch (InterruptedException e) { 27 // e.printStackTrace(); 28 //2.在任務類中catch()塊中處理 29 System.out.println("你可以去死掉了"); 30 return;//結束該執行緒任務 31 } 32 } 33 } 34 } 35 }
四:守護執行緒:
守護執行緒在啟動執行緒之前設定
1 public class Demo02 { 2 /** 3 * 需求:我想在Main()方法結束後終端子程式 4 * 1.為子程式打一個標記 5 * 2.在任務類中catch()塊中處理 6 * @param args 7 * @throws InterruptedException 8 */ 9 public static void main(String[] args) throws InterruptedException { 10 Thread t = new Thread(new MyRunnable()); 11 //將他設定為守護執行緒 12 t.setDaemon(true); 13 t.start(); 14 for(int i = 0;i<5;i++){ 15 System.out.println(Thread.currentThread().getName()+":"+i); 16 Thread.sleep(1000); 17 } 18 } 19 static class MyRunnable implements Runnable{ 20 21 @Override 22 public void run() { 23 for(int i = 0;i<10;i++){ 24 System.out.println(Thread.currentThread().getName()+":"+i); 25 try { 26 Thread.sleep(1000); 27 } catch (InterruptedException e) { 28 // e.printStackTrace(); 29 //2.在任務類中catch()塊中處理 30 System.out.println("你可以去死掉了"); 31 return;//結束該執行緒任務 32 } 33 } 34 } 35 } 36 }
提取出來就是這個樣子:
1 Thread t = new Thread(new MyRunnable()); 2 //將他設定為守護執行緒 3 t.setDaemon(true); 4 t.start();
五:執行緒安全問題:
1.執行緒不安全:當多個執行緒非同步處理同一個資料時,會導致資料不安全問題
2.1)程式碼演示(買票)
1 public class Dem01 { 2 public static void main(String[] args) { 3 //建立任務物件 4 Runnable run = new saleTicket(); 5 //一個任務被多個執行緒執行 6 Thread t1 = new Thread(run); 7 Thread t2 = new Thread(run); 8 Thread t3 = new Thread(run); 9 //啟動執行緒 10 t1.start(); 11 t2.start(); 12 t3.start(); 13 14 } 15 /** 16 * 寫一個任務類,進行賣票 17 */ 18 static class saleTicket implements Runnable{ 19 private //票的數量 20 int count = 10; 21 @Override 22 public void run() { 23 while (count > 0) { 24 System.out.println("正在售票"); 25 try { 26 Thread.sleep(1000); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 count--; 31 System.out.println("還有餘票" + count); 32 } 33 } 34 } 35 }
這個結果顯然是不合理的,原因:當只剩最後一張票時,執行緒A先搶到時間戳,進入迴圈,此時她改變了count的數量變為0,但是,此時在他還沒有跳出迴圈的時候,執行緒B C 都進來了,就這導致後面出現餘票-1 -2的現象。
2.執行緒安全1——同步程式碼塊synchronized
2.1)語法:synchronized(同一個物件){ 排隊執行的程式碼塊 }
2.1)程式碼演示(對買票系統的改進)
1 public class Dem01 { 2 public static void main(String[] args) { 3 //建立任務物件 4 Runnable run = new saleTicket(); 5 //一個任務被多個執行緒執行 6 Thread t1 = new Thread(run); 7 Thread t2 = new Thread(run); 8 Thread t3 = new Thread(run); 9 //啟動執行緒 10 t2.start(); 11 t1.start(); 12 t3.start(); 13 14 } 15 16 /** 17 * 寫一個任務類,進行賣票 18 */ 19 static class saleTicket implements Runnable { 20 //票的數量 21 private int count = 10; 22 //建立一個物件,作為鎖 23 private Object o = new Object(); 24 @Override 25 public void run() { 26 while (true) { 27 synchronized (o) { 28 if (count > 0) { 29 System.out.println("正在售票"); 30 try { 31 Thread.sleep(1000); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 count--; 36 System.out.println(Thread.currentThread().getName()+":還有餘票" + count); 37 } else { 38 break; 39 } 40 } 41 } 42 } 43 } 44 }
誰的執行緒先啟動,誰就先搶到時間戳,在後續中也會較快搶到時間戳,因為他離鎖最近
3.執行緒安全2——同步方法:
3.1)在任務類中,將方法程式碼塊抽去出來,將方法用synchronized修飾
3.2)程式碼演示(對買票的修改)
1 public class Dem01 { 2 public static void main(String[] args) { 3 //建立任務物件 4 Runnable run = new saleTicket(); 5 //一個任務被多個執行緒執行 6 Thread t1 = new Thread(run); 7 Thread t2 = new Thread(run); 8 Thread t3 = new Thread(run); 9 //啟動執行緒 10 t2.start(); 11 t1.start(); 12 t3.start(); 13 14 } 15 16 /** 17 * 寫一個任務類,進行賣票 18 */ 19 static class saleTicket implements Runnable { 20 //票的數量 21 private int count = 10; 22 @Override 23 public void run() { 24 while (true) { 25 boolean flag = sale(); 26 if(!flag){ 27 break; 28 } 29 } 30 } 31 public synchronized boolean sale(){ 32 if (count > 0) { 33 System.out.println("正在售票"); 34 try { 35 Thread.sleep(1000); 36 } catch (InterruptedException e) { 37 e.printStackTrace(); 38 } 39 count--; 40 System.out.println(Thread.currentThread().getName()+":還有餘票" + count); 41 return true; 42 } 43 return false; 44 } 45 } 46 }
同步方法的鎖物件就是建立該類的物件,就像是Runnable run = new saleTicket();只建立了一個任務,所有為同一把鎖
當同步程式碼塊和同步方法同時上鎖是,只有當一個鎖裡面完成後,才可以執行下一個鎖,就像兩個試衣間只有一個門一樣
4.執行緒安全3——顯示鎖Lock:
4.1)自己建立一個鎖物件。鎖Lock 類,他的子類reentrantLock
4.2)Lock l = new reentrantLock(); l.lock()上鎖 l.unlock()解鎖
4.3)程式碼演示(對售票的改進)
1 import java.util.concurrent.locks.Lock; 2 import java.util.concurrent.locks.ReentrantLock; 3 4 public class Dem01 { 5 public static void main(String[] args) { 6 //建立任務物件 7 Runnable run = new saleTicket(); 8 //一個任務被多個執行緒執行 9 Thread t1 = new Thread(run); 10 Thread t2 = new Thread(run); 11 Thread t3 = new Thread(run); 12 //啟動執行緒 13 t2.start(); 14 t1.start(); 15 t3.start(); 16 17 } 18 19 /** 20 * 寫一個任務類,進行賣票 21 */ 22 static class saleTicket implements Runnable { 23 //票的數量 24 private int count = 10; 25 //建立鎖物件 26 private Lock l = new ReentrantLock(); 27 28 @Override 29 public void run() { 30 while (true) { 31 //對需要排隊的程式碼塊進行上鎖 32 l.lock(); 33 if (count > 0) { 34 System.out.println("正在售票"); 35 try { 36 Thread.sleep(1000); 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } 40 count--; 41 System.out.println(Thread.currentThread().getName() + ":還有餘票" + count); 42 } else { 43 break; 44 } 45 //程式碼塊執行完後解鎖 46 l.unlock(); 47 } 48 } 49 } 50 }
5.顯示鎖和隱式鎖的區別
5.1)定義:隱式鎖(Synchronized)是Java的關鍵字,當它用來修飾一個方法或一個程式碼塊時,能夠保證在同一時刻最多隻有一個執行緒執行該程式碼。因為當呼叫 Synchronized修飾的程式碼時,並不需要顯示的加鎖和解鎖的過程,所以稱之為隱式鎖。
顯示鎖(Lock)是一個介面,提供了無條件的、可輪詢的、定時的、可中斷的鎖獲取操作,所有的加鎖和解鎖操作方法都是顯示的,因而稱為顯示鎖。
5.2)區別:(9條訊息) 隱式鎖與顯示鎖的區別_ZL_do_it的部落格-CSDN部落格_顯示鎖和隱式鎖
6.公平鎖和非公平鎖:公平鎖是誰先來排隊,誰就先解鎖,非公平鎖就是誰先搶到誰就先解鎖。Java中預設的為非公平鎖,如何在Java中構建公平鎖:在顯示鎖中創 建 鎖物件時,Lock l = newReentrantLock(true);新增true
7.執行緒死鎖:
7.1)執行緒死鎖的原因:
7.2)程式碼演示:警察對罪犯說,你放了人質,我放了你;罪犯對警察說,你放了我,我放了人質。
1 public class Demo02 { 2 /** 3 * 建立了兩個執行緒,兩個執行緒都在等待對方的回答,很有可能造成執行緒死鎖。 4 * @param args 5 */ 6 public static void main(String[] args) { 7 //建立警察和罪犯物件 8 Culprit c = new Culprit(); 9 Police p = new Police(); 10 //罪犯說話想要得到警察迴應 11 c.say(p); 12 //建立執行緒物件 13 new MyTread(c,p).start(); 14 } 15 16 static class MyTread extends Thread{ 17 private Culprit c; 18 private Police p; 19 20 public MyTread(Culprit c,Police p){ 21 this.c = c; 22 this.p = p; 23 } 24 @Override 25 public void run() { 26 p.say(c); 27 } 28 } 29 static class Culprit{ 30 //罪犯對警察說的話 31 //罪犯對警察說了話之後要得到警察的迴應 32 public synchronized void say(Police p){ 33 System.out.println("你放了我,我放了罪犯"); 34 p.fun(); 35 } 36 //罪犯迴應警察的話 37 public synchronized void fun(){ 38 System.out.println("我把人質留下,你放了我"); 39 } 40 } 41 42 static class Police{ 43 //警察對罪犯說的話 44 //警察在說完話之後要得到罪犯的迴應 45 public synchronized void say(Culprit c){ 46 System.out.println("你放了人質,我放了你"); 47 c.fun(); 48 } 49 //警察迴應罪犯 50 public synchronized void fun(){ 51 System.out.println("把人質留下,你可以走了"); 52 } 53 } 54 }
7.3)如何避免執行緒死鎖:在任何可能導致鎖產生的方法裡面,不要在呼叫其他有可能產生鎖的方法。不然的話極有可能產生死鎖的問題。
8.多執行緒通訊問題:
8.1)舉個栗子來描述一下場景:A執行緒去下載音樂,B執行緒要播放音樂,如何讓A執行緒現在完音樂後去告訴B執行緒你可以播放了,這就涉及到多執行緒間的通訊問題。
8.2)涉及這個問題時常用的方法:Object類中關於執行緒問題的方法:
8.3)程式碼演示(生產者和消費者的關係):這裡用廚師和服務員之間的關係來體現他。廚師做菜的時候,讓服務員這條執行緒休眠,廚師做好飯後,喚醒服務員,讓他去上菜,這個時候廚師休眠,等服務員端回盤子,喚醒廚師,讓他做菜,服務員再次休眠。就這樣迴圈。
1 public class Demo03 { 2 /** 3 * 這是一個生產者和消費者兩個執行緒之間的關係,廚師生產一份飯,服務員端走一份,為了讓他們工作有序,就要讓一個在工作時, 4 * 另一個在睡覺 5 * 6 * @param args 7 */ 8 public static void main(String[] args) { 9 //建立類物件 10 Food f = new Food(); 11 Cook c = new Cook(f); 12 c.start(); 13 Waiter w = new Waiter(f); 14 w.start(); 15 16 } 17 18 static class Food { 19 private String name; 20 private String taste; 21 22 //true為做飯 23 private boolean flag = true; 24 25 //廚師做飯 26 public void setNameAndTaste(String name, String taste) { 27 if (flag) { 28 this.name = name; 29 try { 30 Thread.sleep(1000); 31 } catch (InterruptedException e) { 32 e.printStackTrace(); 33 } 34 this.taste = taste; 35 flag = false; 36 37 //喚醒所有休眠的執行緒 38 this.notifyAll(); 39 try { 40 //做好飯之後睡去,等待服務員喚醒 41 this.wait(); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 } 46 } 47 48 //服務員獲取菜 49 public void getFood() { 50 if (!flag) { 51 try { 52 Thread.sleep(1000); 53 } catch (InterruptedException e) { 54 e.printStackTrace(); 55 } 56 System.out.println("菜的名字是:" + name + ",味道是:" + taste); 57 flag = true; 58 this.notifyAll(); 59 try { 60 this.wait(); 61 } catch (InterruptedException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 } 67 68 static class Cook extends Thread { 69 private Food f; 70 71 public Cook(Food f) { 72 this.f = f; 73 } 74 75 @Override 76 public void run() { 77 for (int i = 0; i < 10; i++) { 78 if (i % 2 == 0) { 79 f.setNameAndTaste("老乾媽小米粥", "香辣味"); 80 } else { 81 f.setNameAndTaste("煎餅果子", "甜辣味"); 82 } 83 } 84 } 85 86 } 87 88 static class Waiter extends Thread { 89 private Food f; 90 91 public Waiter(Food f) { 92 this.f = f; 93 } 94 95 @Override 96 public void run() { 97 for (int i = 0; i < 10; i++) { 98 f.getFood(); 99 } 100 } 101 } 102 103 }
9.執行緒的六種狀態:
10.帶返回值的執行緒Callable
10.1)這是一個介面
10.2)程式碼演示如何使1 import java.util.concurrent.Callable;2 import java.util.concurrent.ExecutionExcepti3 import java.util.concurrent.FutureTask;
4 5 public class Demo04 { 6 public static void main(String[] args) throws ExecutionException, InterruptedException { 7 //2.建立一個Callable物件 8 Callable<Integer> C = new MyCallable(); 9 //3.建立一個任務物件 10 FutureTask<Integer> f = new FutureTask<>(C);//f.isDone()判斷執行緒是否已經執行完了;f.cancel(true/false);決定是否取消執行緒,返回布林型別
11 //4.建立一個執行緒物件,將任務傳給他 12 new Thread(f).start(); 13 //當Callable執行緒呼叫了get方法後,主程式main就要等到子程式執行完後,得到一個返回值後,才可以執行 14 Integer j = f.get(); 15 System.out.println(j); 16 for(int i = 0;i<10;i++){ 17 Thread.sleep(100); 18 System.out.println(i); 19 } 20 } 21 22 //1.建立一個類,實現Callable<T>介面,注意他是泛型的 23 static class MyCallable implements Callable<Integer> { 24 25 @Override 26 public Integer call() throws Exception { 27 for(int i = 0;i<10;i++){ 28 Thread.sleep(100); 29 System.out.println(i); 30 } 31 return 100; 32 } 33 } 34 }
11.執行緒池:
1.概述:就是用來盛放執行緒的
2.執行緒池的底層原理之一
3.執行緒池的分類
1.快取執行緒池
1.2)程式碼演示
1 import java.util.concurrent.*; 2 3 public class Demo05 { 4 public static void main(String[] args) { 5 //1.建立執行緒池物件 6 ExecutorService service = Executors.newCachedThreadPool(); 7 //2.向執行緒池中新增新的任務並且執行他 8 service.execute(new Runnable() { 9 @Override 10 public void run() { 11 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 12 } 13 }); 14 service.execute(new Runnable() { 15 @Override 16 public void run() { 17 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 18 } 19 }); 20 service.execute(new Runnable() { 21 @Override 22 public void run() { 23 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 24 } 25 }); 26 27 //讓主執行緒休眠1秒鐘,此時上述執行緒空閒,則不會在擴容,而用原來的執行緒 28 try { 29 Thread.sleep(1000); 30 } catch (InterruptedException e) { 31 e.printStackTrace(); 32 } 33 service.execute(new Runnable() { 34 @Override 35 public void run() { 36 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 37 } 38 }); 39 } 40 }
2.定長執行緒池
程式碼演示
1 import java.util.concurrent.*; 2 3 public class Demo05 { 4 public static void main(String[] args) { 5 //1.建立執行緒池物件 6 ExecutorService service = Executors.newFixedThreadPool(2); 7 //2.向執行緒池中新增新的任務並且執行他 8 service.execute(new Runnable() { 9 @Override 10 public void run() { 11 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 12 try { 13 Thread.sleep(3000); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 } 18 }); 19 service.execute(new Runnable() { 20 @Override 21 public void run() { 22 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 23 try { 24 Thread.sleep(3000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 }); 30 service.execute(new Runnable() { 31 @Override 32 public void run() { 33 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 34 } 35 }); 36 37 //讓主執行緒休眠1秒鐘,此時上述執行緒空閒,則不會在擴容,而用原來的執行緒 38 try { 39 Thread.sleep(1000); 40 } catch (InterruptedException e) { 41 e.printStackTrace(); 42 } 43 service.execute(new Runnable() { 44 @Override 45 public void run() { 46 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 47 } 48 }); 49 } 50 }
3.單執行緒執行緒池
1 import java.util.concurrent.*; 2 3 public class Demo05 { 4 public static void main(String[] args) { 5 //1.建立執行緒池物件 6 ExecutorService service =Executors.newSingleThreadExecutor(); 7 //2.向執行緒池中新增新的任務並且執行他 8 service.execute(new Runnable() { 9 @Override 10 public void run() { 11 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 12 try { 13 Thread.sleep(3000); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 } 18 }); 19 service.execute(new Runnable() { 20 @Override 21 public void run() { 22 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 23 try { 24 Thread.sleep(3000); 25 } catch (InterruptedException e) { 26 e.printStackTrace(); 27 } 28 } 29 }); 30 31 //讓主執行緒休眠1秒鐘,此時上述執行緒空閒,則不會在擴容,而用原來的執行緒 32 try { 33 Thread.sleep(1000); 34 } catch (InterruptedException e) { 35 e.printStackTrace(); 36 } 37 service.execute(new Runnable() { 38 @Override 39 public void run() { 40 System.out.println(Thread.currentThread().getName()+":"+"鋤禾日當午"); 41 } 42 }); 43 } 44 }
4.週期定長執行緒池
4.1)定時執行一次
在5秒後會打印出 “鋤禾日當午”
1 import java.util.concurrent.*; 2 3 public class Demo05 { 4 public static void main(String[] args) { 5 ScheduledExecutorService service = Executors.newScheduledThreadPool(2); 6 service.schedule(new Runnable() { 7 @Override 8 public void run() { 9 System.out.println("鋤禾日當午"); 10 } 11 },5,TimeUnit.SECONDS); 12 } 13 }
4.2)週期定長執行任務
1 import java.util.concurrent.*; 2 3 public class Demo05 { 4 public static void main(String[] args) { 5 ScheduledExecutorService service = Executors.newScheduledThreadPool(2); 6 service.scheduleAtFixedRate(new Runnable() { 7 @Override 8 public void run() { 9 System.out.println("汗滴禾下土"); 10 } 11 },5,2,TimeUnit.SECONDS); 12 } 13 }
十二:lambda表示式:
1.函數語言程式設計思想
2.格式:Thread t = new Thread((我是引數) ->{我是方法體});
3.僅用來實現介面,實現的介面中只能有一個方法
4.使用的原因:減少冗餘
4.1)冗餘程式碼一:
public class Demo05 { public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
}
static class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("誰知盤中餐");
}
}
}
4.2)冗餘程式碼二:
public class Demo05 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("鋤禾日當午");
}
}).start();
}
}
採用Lamdba表示式:很簡潔
public class Demo05 {
public static void main(String[] args) {
new Thread(() -> System.out.println("鋤禾日當午")).start();
}
}
5.程式碼例項:
1 public class Demo05 { 2 public static void main(String[] args) { 3 //面向物件思想 4 // print(new Main() { 5 // @Override 6 // public int sum(int x, int y) { 7 // return x+y; 8 // } 9 // },100,200); 10 // } 11 12 //Lambda表示式 13 print((int x,int y) ->{return x+y;},100,200); 14 15 } 16 17 public static void print(Main m,int x,int y){ 18 int sum = m.sum(x, y); 19 System.out.println(sum); 20 } 21 static interface Main{ 22 int sum(int x,int y); 23 } 24 }