java基礎-多線程

1.理解程序、進程、線程的概念
程序可以理解爲靜態的代碼
進程可以理解爲執行中的程序。
線程可以理解爲進程的進一步細分,程序的一條執行路徑


2.如何創建java程序的線程(重點)
方式一:繼承於Thread類
class PrintNum extends Thread{
public void run(){
//子線程執行的代碼
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public PrintNum(String name){
super(name);
}
}



public class TestThread {
public static void main(String[] args) {
PrintNum p1 = new PrintNum("線程1");
PrintNum p2 = new PrintNum("線程2");
p1.setPriority(Thread.MAX_PRIORITY);//10
p2.setPriority(Thread.MIN_PRIORITY);//1
p1.start();
p2.start();
}
}
方式二:實現Runnable接口
class SubThread implements Runnable{
public void run(){
//子線程執行的代碼
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}
public class TestThread{
public static void main(String[] args){
SubThread s = new SubThread();
Thread t1 = new Thread(s);
Thread t2 = new Thread(s);

t1.setName("線程1");
t2.setName("線程2");

t1.start();
t2.start();
}
}
兩種方式的對比:聯繫:class Thread implements Runnable
比較哪個好?實現的方式較好。①解決了單繼承的侷限性。②如果多個線程有共享數據的話,建議使用實現方式,同時,共享
數據所在的類可以作爲Runnable接口的實現類。


線程裏的常用方法:start()   run()  currentThread()  getName()  setName(String name) yield() join()  sleep() isAlive() 
     getPriority()  setPriority(int i); wait()  notify() notifyAll()


3.線程的生命週期



                           阻塞


sleep()時間到               sleep()等待同步鎖
獲取同步鎖notify()           wait()/join()
notifyAll()/resume()          suspend()






     start()         獲得CPU執行權
新建----------->就緒<-------------------->運行-------------->死亡
                     失去CPU執行權yield()       正常執行完run()

Error/Except未處理stop()




4.線程的同步機制(重點、難點)
前提:如果我們創建的多個線程,存在着共享數據,那麼就有可能出現線程的安全問題:當其中一個線程操作共享數據時,還未操作完成,
          另外的線程就參與進來,導致對共享數據的操作出現問題。
解決方式:要求一個線程操作共享數據時,只有當其完成操作完成共享數據,其它線程纔有機會執行共享數據。
方式一:同步代碼塊:
synchronized(同步監視器){
//操作共享數據的代碼
}
注:1.同步監視器:俗稱鎖,任何一個類的對象都可以才充當鎖。要想保證線程的安全,必須要求所有的線程共用同一把鎖!
      2.使用實現Runnable接口的方式創建多線程的話,同步代碼塊中的鎖,可以考慮是this。如果使用繼承Thread類的方式,慎用this!
      3.共享數據:多個線程需要共同操作的變量。   明確哪部分是操作共享數據的代碼。


方式二:同步方法:將操作共享數據的方法聲明爲synchronized。
    比如:public synchronized void show(){ //操作共享數據的代碼}
注:1.對於非靜態的方法而言,使用同步的話,默認鎖爲:this。如果使用在繼承的方式實現多線程的話,慎用!
      2.對於靜態的方法,如果使用同步,默認的鎖爲:當前類本身。以單例的懶漢式爲例。 Class clazz = Singleton.class

總結:釋放鎖:wait();
不釋放鎖: sleep()   yield()  suspend() (過時,可能導致死鎖)


死鎖:不同的線程分別佔用對方需要的同步資源不放棄,都在等待對方放棄自己需要的同步資源,就形成了線程的死鎖
死鎖是我們在使用同步時,需要避免的問題!


5.線程的通信:如下的三個方法必須使用在同步代碼塊或同步方法中!
wait():當在同步中,執行到此方法,則此線程“等待”,直至其他線程執行notify()的方法,將其喚醒,喚醒後繼續其wait()後的代碼
notify()/notifyAll():在同步中,執行到此方法,則喚醒其他的某一個或所有的被wait的線程。
>例題:1.兩個線程交替打印1-100自然數   2.生產者、消費者的例子
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章