深入理解多線程(一)
1.多線程的原理
1.1 代碼展示多線程
為了演示多線程,我們用一個代碼來展示多線程的效果:
public class App { public static void main(String[] args) throws
InterruptedException { //子線程 new Thread(() -> { for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":小強"); try {
Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }
}).start(); //主線程 for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":旺財"); Thread.sleep(100);
} } }
流程圖:
程序啟動運行main時候,java虛擬機啟動一個進程,主線程main在main()調(diào)用時候被創(chuàng)建。隨著調(diào)用Thread的對象的start方法,另外一個新的線程也啟動了,這樣,整個應用就在多線程下運行。
通過這張圖我們可以很清晰的看到多線程的執(zhí)行流程。
1.2 圖解多線程時內(nèi)存狀態(tài)圖
多線程執(zhí)行時,在棧內(nèi)存中,其實每一個執(zhí)行線程都有一片自己所屬的棧內(nèi)存空間。進行方法的壓棧和彈棧。
jvm虛擬機中,堆中放的是對象和數(shù)據(jù),棧中放的是方法,方法區(qū)中放的是class類文件
2. 創(chuàng)建線程的兩種方法
2.1 繼承Thread類
public class MyThread extends Thread{ public MyThread(String name){
super(name); } @Override public void run() { for (int i = 0; i < 10; i++) {
System.out.println("小強"); } } } //調(diào)用 new MyThread("myThread").start
2.2 實現(xiàn)Runable接口
public class MyThread implements Runnable{ @Override public void run() {
System.out.println("myThread"); } } //調(diào)用 Thread thread=new Thread(new
MyThread()); thread.start()
我們更傾向于使用匿名內(nèi)部類:
new Thread(() -> { for (int i = 0; i < 20; i++) {
System.out.println(Thread.currentThread().getName()+":小強"); try {
Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } }
}).start();
通過實現(xiàn)Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程序的一個執(zhí)行目標。所有的多線程
代碼都在run方法里面。Thread類實際上也是實現(xiàn)了Runnable接口的類。
在啟動多線程的時候,需要先通過Thread類的構造方法Thread(Runnable target) 構造出對象,然后調(diào)用Thread
對象的start()方法來運行多線程代碼。
實際上所有的多線程代碼都是通過運行Thread的start()方法來運行的。因此,不管是繼承Thread類還是實現(xiàn)
Runnable接口來實現(xiàn)多線程,最終還是通過Thread的對象的API來控制線程的
2.3 兩者的優(yōu)劣
如果一個類繼承Thread,則不適合資源共享。但是如果實現(xiàn)了Runable接口的話,則很容易的實現(xiàn)資源共享。
總結:
實現(xiàn)Runnable接口比繼承Thread類所具有的優(yōu)勢:
* 適合多個相同的程序代碼的線程去共享同一個資源。
* 可以避免java中的單繼承的局限性。
* 增加程序的健壯性,實現(xiàn)解耦操作,代碼可以被多個線程共享,代碼和線程獨立。
* 線程池只能放入實現(xiàn)Runable或Callable類線程,不能直接放入繼承Thread的類。
擴充:在java中,每次程序運行至少啟動2個線程。一個是main線程,一個是垃圾收集線程。因為每當使用
java命令執(zhí)行一個類的時候,實際上都會啟動一個JVM,每一個JVM其實在就是在操作系統(tǒng)中啟動了一個進
程。
熱門工具 換一換