JAVA多线程学习小结
一、線程概念:線程是比進程更小的執(zhí)行單元。一個進程中可以有多個線程
二、多線程優(yōu)點:提高了程序的執(zhí)行效率、充分利用資源、使程序同步執(zhí)行(Java的垃圾回收機制運用了多線程。)
三、進程與線程的區(qū)別
線程與進程的區(qū)別可以歸納為以下4點:
1)地址空間和其它資源(如打開文件):進程間相互獨立,同一進程的各線程間共享。某進程內(nèi)的線程在其它進程不可見。
2)通信:進程間通信IPC,線程間可以直接讀寫進程數(shù)據(jù)段(如全局變量)來進行通信——需要進程同步和互斥手段的輔助,以保證數(shù)據(jù)的一致性。
3)調(diào)度和切換:線程上下文切換比進程上下文切換要快得多。
4)在多線程OS中,進程不是一個可執(zhí)行的實體。
四、創(chuàng)建多線程的兩個方法
1.繼承Thread類。
步驟:
a.繼承Thread類,覆蓋(重寫)run方法。
b.創(chuàng)建線程(即創(chuàng)建對象時線程也就被創(chuàng)建了)。
c.啟動線程。
實例:
class ThreadDemo extends Thread{
public void run(){
//你要執(zhí)行的程序塊
}
}
public class Demo{
public static void main(String args[]){
ThreadDemo td=new ThreadDemo(); //創(chuàng)建線程
td.start();//啟動線程
}
}
2.實現(xiàn)Runnable接口。
步驟:
a.定義類實現(xiàn)Runnable接口。
b.覆蓋Runnable接口中的run方法。
c.通過Thread類建立線程對象。
d.將Runnable接口的子類對象作為實際參數(shù)傳遞給Thread類的構造方法。
e.調(diào)用Thread類的start方法開啟線程。
實例:
class ThreadDemo implements Runnable{
public void run{
//你要執(zhí)行的程序塊
}
}
public class Demo{
public static void main(String args[]){
Thread thread=new Thread(new ThreadDemo());//創(chuàng)建線程
thread.start();//啟動線程
}
}
五、實現(xiàn)方式與繼承方式的區(qū)別
a.繼承Thread:線程代碼存放在Thread子類的run方法中。
b.實現(xiàn)Runnable:線程代碼在接口子類的run方法。
注:使用實現(xiàn)方式的好處是避免了單繼承的局限性。在定義線程時,建議使用實現(xiàn)方式。同時也滿足面向對象設計的模式之一,即面向接口編程的思想。
六、使用多線程時幾個很重要的方法
每個線程都有自己的名稱:默認為:Thread-編號。
兩個方法:getName()、setName().
還可以用構造方法傳入。父類有這個構造方法。可以調(diào)用super(name);
currentThread()獲取當前進程對象。是靜態(tài)的,可以通過類名調(diào)用。
七、多線程的安全問題
原因:當多條語句在操作同一個線程共享數(shù)據(jù)時,一個線程對多條語句只執(zhí)行了一部分,還沒有執(zhí)行完。另一個線程參與進來執(zhí)行,導致共享數(shù)據(jù)的錯誤。
解決辦法:對多條操作共享數(shù)據(jù)的語句,只能讓一個線程都執(zhí)行完,在執(zhí)行過程中,其他線程不可以參與。
Java對多線程的安全問題提供了專業(yè)的解決方式。
就是同步代碼塊。
synchroized(對象)
用synchroized修飾函數(shù)使其成為同步函數(shù),給某個線程加鎖,上鎖后不允許其他線程同時來共享此數(shù)據(jù)塊。
同步函數(shù)用的是哪一個鎖?
函數(shù)需要被對象調(diào)用。那么函數(shù)都有一個所屬對象引用。就是this。
所有同步函數(shù)使用的鎖是this.
兩個要點:1.多個線程存在。2.同一個鎖。
如果同步函數(shù)被靜態(tài)類修飾后,使用的鎖是什么呢?
在靜態(tài)方法中不可以定義this.靜態(tài)進內(nèi)存,內(nèi)存中沒有本類對象,但是一定有該類對應的字節(jié)碼文件對象。類名.class?? 該對象的類型是Class.
SO :靜態(tài)的同步方法,使用的鎖是該方法所在類的字節(jié)碼文件對象,類名.class.
八、多線程中thread.run()與thread.start()的區(qū)別
thread.start()開啟了線程,才會實現(xiàn)程序的多線程執(zhí)行。
thread.run()方法僅僅只是調(diào)用了方法,沒開啟線程,也就無法實現(xiàn)多線程。運行時不會不斷的先后搶占CPU資源,而是調(diào)用后全部執(zhí)行完。
九、單例模式中的多線程(*)
//單例模式:私有化構造方法不允許類外創(chuàng)建對象,一般推薦使用餓漢式,因為懶漢式容易產(chǎn)生線程不安全問題
/*
餓漢式
class Single{
?? ?private static final Single s=new Single();
?? ?private Single();
?? ?public static Single getInstance(){
?? ??? ?return s;
?? ?}
}
*/
class Single {????????????? //懶漢式
?? ?private static Single s=null;
?? ?private Single(){}
?? ?public static Single getInstance(){
?? ??? ?if(s==null){
?? ??? ??? ?synchronized(Single.class){? //同步修飾防止發(fā)生線程不安全問題
?? ??? ??? ??? ?if(s==null)
?? ??? ??? ??? ??? ?s=new Single();
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
public class SingleDemo {
?? ?public static void main(String[] args) {
?? ??? ?
?? ?}
}
十、死鎖問題(*)
class Test implements Runnable
{
?? ?private boolean flag;
?? ?Test(boolean flag){
?? ??? ?this.flag=flag;
?? ?}
?? ?public void run(){
?? ??? ?if(flag){
?? ??? ??? ?synchronized(MyLock.locka){
?? ??? ??? ??? ??? ?System.out.println("if MyLock.locka");
?? ??? ??? ??? ?synchronized(MyLock.lockb){
?? ??? ??? ??? ??? ?System.out.println("if MyLock.lockb");
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ??? ?else{
?? ??? ??? ?synchronized(MyLock.lockb){
?? ??? ??? ??? ??? ?System.out.println("else MyLock.lockb");
?? ??? ??? ??? ?synchronized(MyLock.locka){
?? ??? ??? ??? ??? ?System.out.println("else MyLock.locka");
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ?}
}
class MyLock
{
?? ?static Object? locka=new Object();
?? ?static Object? lockb=new Object();
}
class DeadLockTest {
?? ?public static void main(String[] args) {
?? ??? ?Thread t1=new Thread(new Test(true));
?? ??? ?Thread t2=new Thread(new Test(false));
?? ??? ?t1.start();
?? ??? ?t2.start();
?? ?}
}
轉載于:https://www.cnblogs.com/freedomwolf/p/5693291.html
總結
以上是生活随笔為你收集整理的JAVA多线程学习小结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios 消除 字符串 首尾空格
- 下一篇: 转载:T-SQL语句大全