文檔目錄:html
1、進程與線程java
2、多線程的實現安全
3、獲取線程名與線程對象多線程
5、線程調度與優先級ide
6、線程安全(重點)this
7、死鎖spa
---------------------------------------分割線:正文--------------------------------------------------------線程
一、基本概念
進程是一個應用程序。
線程是一個進程中的執行場景/執行單元。
一個進程能夠啓動多個線程
二、舉例說明進程與線程、
java輸出helloworld回車,先啓動JVM是一個進行,JVM再啓動一個主線程調用main方法,同時再啓動一個垃圾回收線程負責看護,回收垃圾,至少兩個線程併發。
三、進程與線程的關係
阿里巴巴:進程A
馬雲:阿里巴巴的一個線程
張小龍:阿里巴巴的一個線程
京東:進程B
強東:jd的一個線程
奶茶:jd的一個吸納還曾
進程A與B內存獨立不共享(阿里與jd資源不共享)
線程A與線程B:JAVA中堆內存與方法區內存共享,棧內存獨立
四、多線程機制的目的
提升程序的處理效率
一、第一種實現方式:繼承java.lang.Thread方法,並從新run方法
1 package JAVAADVANCE; 2 public class TestAdvance37TestThread01 { 3 //這裏是main方法,這裏的代碼屬於主線程,在主線程中運行
4 public static void main(String[] args) { 5 //新建一個分支線程對象,
6 MyThread myThread=new MyThread(); 7 //start開啓新的棧空間,啓動一個分支線程,啓動成功線程自動調用run方法,而直接調用MyThread.run()不會啓動多線程
8 myThread.start(); 9 //這裏的代碼運行在主線程中
10 for (int i=0;i<100;i++){ 11 System.out.println("主線程------->"+i); 12 } 13 } 14 } 15 class MyThread extends Thread{ 16 @Override 17 public void run() { 18 //編寫程序,這段代碼在分支線程中執行
19 for(int i=0;i<100;i++){ 20 System.out.println("分支線程------->"+i); 21 } 22 } 23 }
查看執行結果片斷:主線程與分支線程是併發的
1 主線程------->91
2 主線程------->92
3 分支線程------->0
4 主線程------->93
5 分支線程------->1
6 主線程------->94
7 主線程------->95
二、第二種實現方式:編寫一個類,實現java.lang.Runnable接口,實現run方法(建議使用,由於此類還能夠繼承其餘方法)
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread02 { 4 public static void main(String[] args) { 5 //建立線程對象,將可運行的對象封裝成線程對象
6 Thread t = new Thread(new MyRunnable()); 7 t.start(); 8 //這裏的代碼運行在主線程中
9 for (int i = 0; i < 100; i++) { 10 System.out.println("主線程------->" + i); 11 } 12 } 13 } 14 class MyRunnable implements Runnable{ 15 @Override 16 public void run() { 17 for(int i=0;i<100;i++){ 18 System.out.println("分支線程------->"+i); 19 } 20 } 21 }
查看執行結果片斷:主線程與分支線程是併發的
1 分支線程------->54
2 主線程------->4
3 主線程------->5
4 分支線程------->55
5 主線程------->6
6 主線程------->7
三、第三種實現方式:採用匿名內部類方法
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread03 { 4 public static void main(String[] args) { 5 Thread t = new Thread(new Runnable() { 6 @Override 7 public void run() { 8 for (int i = 0; i < 100; i++) { 9 System.out.println("分支線程------->" + i); 10 } 11 } 12 }); 13 //啓動分支線程
14 t.start(); 15 for (int i = 0; i < 100; i++) { 16 System.out.println("主線程------->" + i); 17 } 18 } 19 }
查看執行結果片斷:主線程與分支線程是併發的
1 分支線程------->10
2 主線程------->12
3 分支線程------->11
4 主線程------->13
5 分支線程------->12
6 主線程------->14
7 分支線程------->13
四、第四種實現方式:實現callable接口(JDK8新特性)
(1)優先與缺點:
優勢:能夠拿到線程的執行結果
缺點:效率比較低,獲取結果時,當前線程受阻塞
(2)實現方式
1 package JAVAADVANCE; 2
3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.Future; 6 import java.util.concurrent.FutureTask; 7
8 public class TestAdvance37TestThread10 { 9 public static void main(String[] args) { 10 //建立一個將來任務對象,須要黑一個callable接口實現類的對象,這裏使用匿名內部類
11 FutureTask task=new FutureTask(new Callable() { 12 @Override 13 public Object call() throws Exception { 14 //call()相似run方法,可是有返回值 15 //模擬行爲
16 System.out.println("call method begin"); 17 Thread.sleep(1000*10); 18 System.out.println("call method end"); 19 int a=100; 20 int b=200; 21 return a+b; //自動裝箱,300結果變爲Integer
22 } 23 }); 24 //建立線程對象
25 Thread t=new Thread(task); 26 //啓動線程
27 t.start(); 28 //獲取t線程的返回結果
29 try { 30 Object obj=task.get(); 31 System.out.println("線程的執行結果爲:"+obj); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } catch (ExecutionException e) { 35 e.printStackTrace(); 36 } 37 //main方法這裏的程序要想執行必須等待get方法
38 System.out.println("hello world"); 39
40 } 41 }
查看執行結果:hello world在10秒後展現
call method begin call method end 線程的執行結果爲:300 hello world
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread04 { 4 public static void main(String[] args) { 5 //獲取當前線程對象
6 Thread t1=Thread.currentThread(); 7 System.out.println("main方法下的當前線程名:"+t1.getName()); 8 MyThread t2=new MyThread(); 9 //查看線程默認名
10 System.out.println("線程默認名:"+t2.getName()); 11 t2.setName("ttttt"); 12 System.out.println("修改後的線程名:"+t2.getName()); 13 } 14 }
查看執行結果
main方法下的當前線程名:main 線程默認名:Thread-0 修改後的線程名:ttttt
一、概念:
(1)sleep爲靜態方法
(2)參數爲毫秒
(3)做用:讓當前線程進入休眠,進入"阻塞狀態",放棄佔用cpu時間片,讓給其餘線程使用
二、舉例說明sleep方法
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread05 { 4 public static void main(String[] args) { 5 //讓當前進程進入休眠狀態,睡眠5秒
6 try { 7 Thread.sleep(1000*5); 8 System.out.println("hello world"); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 } 13 }
5秒後控制檯打印hello world
三、停止進程的睡眠
注:run()方法內只能try catch,不能throws,由於子類不能比父類拋出更多的異常
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread06 { 4 public static void main(String[] args) { 5 Thread t=new Thread(new MyRunnable2()); 6 t.setName("t"); 7 t.start(); 8 try { 9 Thread.sleep(1000*5); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 //終於線程的睡眠
14 t.interrupt(); 15 } 16 } 17
18 class MyRunnable2 implements Runnable{ 19 @Override 20 public void run() { 21 System.out.println(Thread.currentThread().getName()+"---->begin"); 22 try { 23 Thread.sleep(1000*60*60*24*365); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 System.out.println(Thread.currentThread().getName()+"----->end"); 28 } 29 }
查看運行結果:sleep5秒後出現異常信息,進程被停止
t---->begin java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at JAVAADVANCE.MyRunnable2.run(TestAdvance37TestThread06.java:23) at java.lang.Thread.run(Thread.java:748) t----->end Process finished with exit code 0
四、強行終止進程執行
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread07 { 4 public static void main(String[] args) { 5 Thread t=new Thread(new MyRunnable3()); 6 t.setName("t"); 7 t.start(); 8 try { 9 Thread.sleep(1000*5); 10 } catch (InterruptedException e) { 11 e.printStackTrace(); 12 } 13 t.stop(); 14 } 15 } 16
17 class MyRunnable3 implements Runnable{ 18 @Override 19 public void run() { 20 for(int i=0;i<10;i++){ 21 System.out.println(Thread.currentThread().getName()+"------>"+i); 22 try { 23 Thread.sleep(1000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 } 29 }
stop方法的缺點:容易丟失數據,直接將線程殺死
五、合理的終止一個線程的執行
1 package JAVAADVANCE; 2
3 import static java.lang.Thread.sleep; 4
5 public class TestAdvance37TestThread08 { 6 public static void main(String[] args) { 7 MyRunnable4 r=new MyRunnable4(); 8 Thread t=new Thread(r); 9 t.setName("t"); 10 t.start(); 11 try { 12 sleep(1000*5); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 //何時停止t改成false
17 r.run=false; 18 } 19 } 20
21 class MyRunnable4 implements Runnable{ 22 //打一個布爾標記
23 boolean run=true; 24 @Override 25 public void run() { 26
27 for(int i=0;i<10;i++){ 28 if(run){ 29 System.out.println(Thread.currentThread().getName()+"----->"+i); 30 try { 31 sleep(1000); 32 } catch (InterruptedException e) { 33 e.printStackTrace(); 34 } 35 } 36
37 else { 38 //save保存代碼 39 //終止當前線程
40 return; 41 } 42 } 43 } 44 }
查看執行結果,5秒後執行結果。
t----->0 t----->1 t----->2 t----->3 t----->4
一、分兩種:搶佔式調度模型與均分式調度模型,java屬於前者
二、經常使用方法:
(1)設置線程的優先級:void setPrority()
(2)獲取線程的優先級:int getPrority()
優先級分:1,5,10(最高)
(3)進程讓位:static void yield()
(4)合併線程程:t.join() //當前線程阻塞,t線程加入當前線程中
6、線程安全(重點)
一、含義:
不出現異常,也不會出現錯誤,程序僵持,難以調試
二、舉例:
1 package JAVAADVANCE; 2
3 public class TestAdvance37TestThread09 { 4 public static void main(String[] args) { 5 Object o1=new Object(); 6 Object o2=new Object(); 7 Thread t1=new MyThread1(o1,o2); 8 Thread t2=new MyThread2(o1,o2); 9 t1.start(); 10 t2.start(); 11 } 12 } 13 class MyThread1 extends Thread{ 14 Object o1; 15 Object o2; 16 public MyThread1(Object o1,Object o2){ 17 this.o1=o1; 18 this.o2=o2; 19 } 20 public void run(){ 21 synchronized (o1){ 22 try { 23 Thread.sleep(1000); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 synchronized (o2){} 28 } 29 } 30 } 31 class MyThread2 extends Thread{ 32 Object o1; 33 Object o2; 34 public MyThread2(Object o1,Object o2){ 35 this.o1=o1; 36 this.o2=o2; 37 } 38 public void run(){ 39 synchronized (o2){ 40 try { 41 Thread.sleep(1000); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 synchronized (o1){} 46 } 47 } 48 }
程序運行一直不會結束也沒有返回
三、解決方案:
程序編寫使用時儘可能避免synchronized 方法嵌套使用