1. 程式人生 > >總結下自己理解的多線程知識

總結下自己理解的多線程知識

多線程

1.多線程概念
進程:一個正在運行的程序就可以看作是一個進程。每個進程都有自己獨立
的內存空間。
線程:一個程序的執行順序控制流就可以看作是一個線程。
進程和線程的區別:
1.每個進程都有獨立的代碼和數據空間(進程上下文),進程間的切換會有較
大的開銷。
2.線程可以看成時輕量級的進程,同一類線程共享代碼和數據空間,每個
線程有獨立的運行棧和程序計數器(PC),線程切換的開銷小。
多進程:在操作系統中能同時運行多個程序(任務)
多線程:在同一應用程序中有多個順序流同時執行,在一個進程裏可以有1條
或多條線程,但是至少要有一條線程。多線程能夠提高程序的執行效率。
線程和進程一樣分為五個階段:創建、就緒、運行、阻塞、終止。
2.main線程(主線程)
在程序裏有一個public static void main(String[] args)方法,這個方法是程序
的入口,這是一個固定的寫法。
當程序啟動時,JVM虛擬機會自動的創建main線程(主線程),在主線程裏
會自動的調用main()方法,就會執行main()方法裏的代碼。我們編寫的代碼都
是寫在main()方法中,所以我們寫的代碼都是在主線程(main線程)執行的。
3.創建子線程的(兩種方式)
Thread類:描述線程裏的屬性(線程的名稱,線程的優先級,線程執行的任
務),基於面向對象的思想就把線程的屬性封裝成Thread類。
Thread類的方法:
a.普通方法
getName():獲取線程對象的名稱。
start():啟動線程。
b.靜態方法:類名.方法名
currentThread():獲取當前正在執行的線程對象。
Thread curThead = Thread.currentThread();
System.out.println(curThead.getName());
3.1創建子線程方式一:
a.聲明一個類繼承Thread類,並重寫run()方法。

技術分享圖片
3.2創建子線程方式二:
a.實現Runnable接口,重寫run()方法。

技術分享圖片
b.通過匿名內部類開啟子線程
技術分享圖片
4.Thread類常用方法
靜態方法:類名.方法名()
currentThread():返回一個正在執行的線程對象。
sleep():讓當前線程睡醒指定毫秒數。
普通方法:
getName():獲取線程對象的名稱
start():開啟子線程
(1)sleep():讓當前線程睡醒指定毫秒數,不會釋放鎖。是Thread類的靜態方法,可以在任意位置使用。
//睡眠1秒
Thread.sleep(1000);
(2)isAlive():判斷線程是否還“活”著,即線程是否還未終止。
線程的優先級:
線程的優先級越高表示這個線程執行的概率越高。
線程優先級值的範圍:1~10,最低1,最高10.
(3)getPriority():獲取線程的優先級。
(4)setPriority():設置線程的優先級。
(5)join():調用某線程的該方法,將當前線程與該線程“合並”,即等待該線程結束,再恢復當前線程的運行。
(6)yield():讓出CPU,當前線程進入就緒隊列等待調度。
(7)wait():讓線程進入等待池wait pool進入阻塞狀態並釋放鎖,直到notify()或者notifyAll()喚醒。是object類的對象方法,只能在互斥鎖(同步鎖)裏使用。
(8)notify()或者notifyAll()喚醒等待池wait pool裏的線程。
5.互斥鎖(同步鎖)(重點)
解決多線程安全問題就是用同步鎖。
a.給代碼加鎖
public void run()
{
Thread.sleep(500);
//在run()方法裏的訪問變量加鎖
//類名.class是鑰匙
synchronized(類名.class)
{//開始加鎖
xinXi1.num++;
System.out.println(Thread.currentThread().getName() + xinXi1.num);
}//釋放鎖
}
例子:
public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("線程1");
subThread subThread = new subThread("線程2");
addThread.start();
subThread.start();
}
}
//加法子線程繼承Thread
class addThread extends Thread{
public addThread(String name){

    super(name);
}
@Override
public void run()
{
    try
    {
        addThread.sleep(3000);
    } catch (InterruptedException e)
    {
        e.printStackTrace();
    }

//給代碼加鎖
synchronized (xinXi1.class)
{
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法後="+xinXi1.num);
}
}
}
//減法子線程繼承Thread
class subThread extends Thread{
public subThread(String name){

    super(name);
}
@Override
public void run()
{
    try
    {
        subThread.sleep(3000);
    } catch (InterruptedException e)
    {
        e.printStackTrace();
    }
    synchronized (xinXi1.class)
    {
        xinXi1.num--;
        System.out.println(subThread.currentThread().getName()+"減法後="+xinXi1.num);
    }       
}

}
b.給方法加鎖
例子:

public class xinXi1
{
public static int num = 11;
public static void main(String[] args)
{
System.out.println("num="+xinXi1.num);
addThread addThread = new addThread("線程1");
subThread subThread = new subThread("線程2");
addThread.start();
subThread.start();
}
//給方法加鎖
public static synchronized void add(){
xinXi1.num++;
System.out.println(addThread.currentThread().getName()+"加法後="+xinXi1.num);
}
//給方法加鎖
public static synchronized void sub(){
xinXi1.num--;
System.out.println(subThread.currentThread().getName()+"減法後="+xinXi1.num);
}

}
class addThread extends Thread{
public addThread(String name){super(name);
}
@Override
br/>super(name);
}
@Override
{
try
{
addThread.sleep(3000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//線程裏調用方法
xinXi1.add();
}
}
class subThread extends Thread{
public subThread(String name){super(name);
}
@Override
br/>super(name);
}
@Override
{
try
{
subThread.sleep(3000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
//線程裏調用方法
xinXi1.sub();
}
}
註意事項:
1.synchronized(){}大括號裏的代碼就是加鎖的代碼,註意加鎖會影響程序
的性能,除非涉及到多線程數據安全才需要加鎖,其他情況建議不要加鎖。
加鎖的代碼要盡量的少。

總結下自己理解的多線程知識