第一篇:【java總結(jié)】多線程(基礎(chǔ)篇)
【java總結(jié)】多線程(基礎(chǔ)篇)
Java的線程分為5種狀態(tài):創(chuàng)建、就緒、運(yùn)行、阻塞和死亡。
創(chuàng)建:
在java種創(chuàng)建線程的方式有兩種,一種是通過(guò)繼承Thread類并且重寫run方法,run方法中執(zhí)行的代碼便是線程執(zhí)行的代碼。另一種是通過(guò)實(shí)現(xiàn)Runnable接口,并將該接口實(shí)例傳入一個(gè)Thread實(shí)例。通過(guò)對(duì)Thread的引用調(diào)用start()方法,即可讓線程進(jìn)入就緒狀態(tài)。如果直接調(diào)用run方法,并不會(huì)生成線程,而是在當(dāng)前線程中把run()當(dāng)做一個(gè)普通方法執(zhí)行。[java] view plain copy public class Thread1 extends Thread{
/*
* 實(shí)現(xiàn)線程的方法一:通過(guò)繼承Thread并覆蓋run()方法來(lái)實(shí)現(xiàn)多線程。
*/
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+“線程開始!”);
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+“ ”+i);
try{
sleep((int)Math.random()*10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+“線程結(jié)束!”);
}
}
[java] view plain copy public class Thread2 implements Runnable{
/*
* 實(shí)現(xiàn)線程的方法二:通過(guò)實(shí)現(xiàn)Runnable接口來(lái)實(shí)現(xiàn)多線程
* 實(shí)現(xiàn)Runnable接口比繼承Thread類所具有的優(yōu)勢(shì):
* 1):適合多個(gè)相同的程序代碼的線程去處理同一個(gè)資源
* 2):可以避免java中的單繼承的限制
* 3):增加程序的健壯性,代碼可以被多個(gè)線程共享,代碼和數(shù)據(jù)獨(dú)立
*/
@Override
public void run(){
System.out.println(Thread.currentThread().getName()+“線程開始!”);
for(i004km.cnnt i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+“ ”+i);
try{
Thread.sleep((int)Math.random()*10);
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+“線程結(jié)束!”);
}
}
就緒:
處于就緒狀態(tài)的線程隨時(shí)可以被JVM的線程調(diào)度器調(diào)度,進(jìn)入運(yùn)行狀態(tài)。對(duì)于處于就緒狀態(tài)的線程,我們并不能對(duì)他們被調(diào)度的順序進(jìn)行任何估計(jì),也就是說(shuō),線程的執(zhí)行順序是不可預(yù)測(cè)的。處于運(yùn)行狀態(tài)的線程,通過(guò)調(diào)用yield()方法,可以返回到就緒狀態(tài),然而它有可能瞬間被再次調(diào)度。yield()方法把運(yùn)行機(jī)會(huì)讓給了同等優(yōu)先級(jí)的其他線程。
[java] view plain copy public class ThreadYield extends Thread{
@Override
public void run(){
for(int i = 1;i <= 50;i++){
System.out.println(“" +Thread.currentThread().getName()+ ”-----“ + i);
// 當(dāng)i==25時(shí),該線程就會(huì)把CPU時(shí)間讓掉,讓其他或者自己的線程執(zhí)行(也就是誰(shuí)先搶到誰(shuí)執(zhí)行)
if(i==25){
this.yield();
}
}
}
}
[java] view plain copy public class ThreadYieldTest {
/*
* Thread.yield():暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
* 該方法讓當(dāng)前線程回到可運(yùn)行狀態(tài),以允許其他具有相同優(yōu)先級(jí)的線程獲得運(yùn)行機(jī)會(huì)。
* 但是實(shí)際中無(wú)法保證yield()達(dá)到讓步目的,因?yàn)楫?dāng)前線程有可能被線程調(diào)度程序再次選中。
*/
public static void main(String[] args){
ThreadYield thread1=new ThreadYield();
ThreadYield thread2=new ThreadYield();
thread1.start();
thread2.start();
}
}
運(yùn)行:
處于運(yùn)行狀態(tài)的線程隨時(shí)有可能被線程調(diào)度器換下,進(jìn)入到就緒狀態(tài)。想要規(guī)定線程的順序,需要調(diào)用join方法,對(duì)某個(gè)線程 的調(diào)用join方法,則主線程會(huì)阻塞到該線程執(zhí)行完后再繼續(xù)執(zhí)行?;蛘呤褂靡环N叫做鎖的機(jī)制(下文會(huì)提及)。當(dāng)一個(gè)線程完成它run()里面的所有工作時(shí),線程會(huì)自動(dòng)死亡。調(diào)用sleep(),線程會(huì)進(jìn)入休眠,并且在一段時(shí)間內(nèi)不會(huì)被再度調(diào)用。睡眠時(shí)間過(guò)后,線程才再次進(jìn)入就緒隊(duì)列中。
[java] view plain copy public class ThreadJoinTest {
/*
* join是Thread類的一個(gè)方法,作用是等待該線程終止。例如對(duì)子線程A調(diào)用join()方法,* 主線程將等待子線程A終止后才能繼續(xù)后面的代碼。
*/
public static void main(String[] args){
System.out.println(”主線程開始!“);
Thread1 thread1=new Thread1();
Thread1 thread2=new Thread1();
thread1.start();
thread2.start();
try{
thread1.join();
}catch(InterruptedException e){
e.printStackTrace();
}
try{
thread2.join();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(”主線程結(jié)束!“);
} }
死亡:
線程因?yàn)榇a執(zhí)行完畢而正常結(jié)束自身線程,或者因?yàn)槟承┊惓6Y(jié)束線程。
[java] view plain copy public class ThreadInterrupt extends Thread{
/*
* wait()和sleep()都可以通過(guò)interrupt()方法 打斷線程的暫停狀態(tài),從而使線程立刻拋出Interrupted004km.cnt i=0;i<3;i++){
new Thread(new Runnable(){
@Override
public void run(){
ThreadSynchronizedTest x=new ThreadSynchronizedTest();
System.out.println(”value=“+x.getNext());
System.out.println(”value=“+x.getNext2());
System.out.println(”value=“+x.getNext3());
}
}).start();
}
}
}
阻塞:
阻塞跟Obj.wait(),Obj.notify()方法有關(guān)。當(dāng)調(diào)用wait方法時(shí),線程釋放對(duì)象鎖,進(jìn)入阻塞狀態(tài),直到其他線程喚醒它。
Obj.wait(),與Obj.notify()必須要與synchronized(Obj)一起使用
Obj.notify()作用:對(duì)對(duì)象鎖的喚醒操作。notify()調(diào)用后,并不是馬上就釋放對(duì)象鎖的,而 是在相應(yīng)的synchronized(){}語(yǔ)句塊執(zhí)行結(jié)束,自動(dòng)釋放鎖后,JVM會(huì)在wait()對(duì)象鎖的線 程中隨機(jī)選取一線程,賦予其對(duì)象鎖,喚醒線程,繼續(xù)執(zhí)行。
Obj.wait()作用:線程在獲取對(duì)象鎖后,主動(dòng)釋放對(duì)象鎖,同時(shí)本線程休眠,直到有其它線程調(diào)用
對(duì)象的notify()喚醒該線程,才能繼續(xù)獲取對(duì)象鎖,并繼續(xù)執(zhí)行。下面我們通過(guò)一道題目來(lái)加深理解。
問(wèn)題:建立三個(gè)線程,A線程打印10次A,B線程打印10次B,C線程打印10次C,要求線程同時(shí)運(yùn)行,交替打印10次ABC。代碼如下:
[java] vie004km.cnw plain copy public class ThreadPrintABCTest {
/*
* 建立三個(gè)線程,A線程打印10次A,B線程打印10次B,C線程打印10次C,要求線程同時(shí)運(yùn)行,交替打印10次ABC。
*
*/
public static void main(String[] args)throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
ThreadPrintABC pa = new ThreadPrintABC(”A“, c, a);
ThreadPrintABC pb = new ThreadPrintABC(”B“, a, b);
ThreadPrintABC pc = new ThreadPrintABC(”C“, b, c);
new Thread(pa).start();
Thread.sleep(100);//確保按順序A、B、C執(zhí)行
new Thread(pb).start();
Thread.sleep(100);
new Thread(pc).start();
Thread.sleep(100);
}
}
[java] view plain copy public class ThreadPrintABC implements Runnable{
private String data;
private Object pre;
private Object self;
public ThreadPrintABC(String data,Object pre,Object self){
this.data=data;
this.pre=pre;
this.self=self;
}
@Override
public void run(){
int count=10;
while(count>0){
synchronized(pre){
synchronized(self){
if(data==”C"){
System.out.println(data);
}else{
System.out.print(data);
}
count--;
self.notify();
}
try{
pre.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
}
死鎖:
兩個(gè)或兩個(gè)以上的線程在執(zhí)行過(guò)程當(dāng)中,由于競(jìng)爭(zhēng)資源或者彼此之間通信而造成的一種阻塞現(xiàn)象。比如,當(dāng)線程A調(diào)用wait()方法等待線程B的喚醒,而線程B同時(shí)也調(diào)用wait方法等待線程A的喚醒,這時(shí)兩個(gè)線程將陷入僵持狀態(tài),永遠(yuǎn)處在阻塞狀態(tài),成為死鎖進(jìn)程,即兩個(gè)線程永遠(yuǎn)也不會(huì)被執(zhí)行。
sleep方法與wait方法的區(qū)別及細(xì)節(jié):
sleep()睡眠時(shí),保持對(duì)象鎖,仍然占有該鎖;而wait()睡眠時(shí),釋放對(duì)象鎖。sleep()使當(dāng)前線程進(jìn)入停滯狀態(tài)(阻塞當(dāng)前線程),讓出CPU的使用、目的是不讓當(dāng)前線程獨(dú)自霸占該進(jìn)程所獲的CPU資源,以留一定時(shí)間給其他線程執(zhí)行的機(jī)會(huì);sleep()是Thread類的Static(靜態(tài))的方法;因此他不能改變對(duì)象的機(jī)鎖,所以當(dāng)在一個(gè)Synchronized塊中調(diào)用Sleep()方法是,線程雖然休眠了,但是對(duì)象的鎖并木有被釋放,其他線程無(wú)法訪問(wèn)這個(gè)對(duì)象(即使睡著也持有對(duì)象鎖)。在sleep()休眠時(shí)間期滿后,該線程不一定會(huì)立即執(zhí)行,這是因?yàn)槠渌€程可能正在運(yùn)行而且沒(méi)有被調(diào)度為放棄執(zhí)行,除非此線程具有更高的優(yōu)先級(jí)。
wait()方法是Object類里的方法;當(dāng)一個(gè)線程執(zhí)行到wait()方法時(shí),它就進(jìn)入到一個(gè)和該對(duì)象相關(guān)的等待池中,同時(shí)失去(釋放)了對(duì)象的機(jī)鎖(暫時(shí)失去鎖,wait(long timeout)超時(shí)時(shí)間到后還需要返還對(duì)象鎖);其他線程可以訪問(wèn);
wait()使用notify或者notifyAlll或者指定睡眠時(shí)間來(lái)喚醒當(dāng)前等待池中的線程。wiat()必須放在synchronizedblock中,否則扔出”java.lang.IllegalMonitorStateException“異常。
第二篇:Java多線程編程總結(jié)
Java多線程編程總結(jié)
2007-05-17 11:21:59 標(biāo)簽:java 多線程
原創(chuàng)作品,允許轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章 原始出處、作者信息和本聲明。否則將追究法律責(zé)任。http://lavasoft.blog.51cto.com/62575/27069
Java多線程編程總結(jié)
下面是Java線程系列博文的一個(gè)編目:
Java線程:概念與原理 Java線程:創(chuàng)建與啟動(dòng)
Java線程:線程棧模型與線程的變量 Java線程:線程狀態(tài)的轉(zhuǎn)換 Java線程:線程的同步與鎖 Java線程:線程的交互 Java線程:線程的調(diào)度-休眠 Java線程:線程的調(diào)度-優(yōu)先級(jí) Java線程:線程的調(diào)度-讓步 Java線程:線程的調(diào)度-合并 Java線程:線程的調(diào)度-守護(hù)線程 Java線程:線程的同步-同步方法 Java線程:線程的同步-同步塊
Java線程:并發(fā)協(xié)作-生產(chǎn)者消費(fèi)者模型 Java線程:并發(fā)協(xié)作-死鎖 Java線程:volatile關(guān)鍵字 Java線程:新特征-線程池
Java線程:新特征-有返回值的線程 Java線程:新特征-鎖(上)Java線程:新特征-鎖(下)Java線程:新特征-信號(hào)量 Java線程:新特征-阻塞隊(duì)列 Java線程:新特征-阻塞棧 Java線程:新特征-條件變量 Java線程:新特征-原子量 Java線程:新特征-障礙器 Java線程:大總結(jié)
----
下面的內(nèi)容是很早之前寫的,內(nèi)容不夠充實(shí),而且是基于Java1.4的內(nèi)容,Java5之后,線程并發(fā)部分?jǐn)U展了相當(dāng)多的內(nèi)容,因此建議大家看上面的系列文章的內(nèi)容,與時(shí)俱進(jìn),跟上Java發(fā)展的步伐。----
一、認(rèn)識(shí)多任務(wù)、多進(jìn)程、單線程、多線程 要認(rèn)識(shí)多線程就要從操作系統(tǒng)的原理說(shuō)起。
以前古老的DOS操作系統(tǒng)(V 6.22)是單任務(wù)的,還沒(méi)有線程的概念,系統(tǒng)在每次只能做一件事情。比如你在copy東西的時(shí)候不能rename文件名。為了提高系統(tǒng)的利用效率,采用批處理來(lái)批量執(zhí)行任務(wù)。
現(xiàn)在的操作系統(tǒng)都是多任務(wù)操作系統(tǒng),每個(gè)運(yùn)行的任務(wù)就是操作系統(tǒng)所做的一件事情,比如你在聽歌的同時(shí)還在用MSN和好友聊天。聽歌和聊天就是兩個(gè)任務(wù),這個(gè)兩個(gè)任務(wù)是“同時(shí)”進(jìn)行的。一個(gè)任務(wù)一般對(duì)應(yīng)一個(gè)進(jìn)程,也可能包含好幾個(gè)進(jìn)程。比如運(yùn)行的MSN就對(duì)應(yīng)一個(gè)MSN的進(jìn)程,如果你用的是windows系統(tǒng),你就可以在任務(wù)管理器中看到操作系統(tǒng)正在運(yùn)行的進(jìn)程信息。
一般來(lái)說(shuō),當(dāng)運(yùn)行一個(gè)應(yīng)用程序的時(shí)候,就啟動(dòng)了一個(gè)進(jìn)程,當(dāng)然有些會(huì)啟動(dòng)多個(gè)進(jìn)程。啟動(dòng)進(jìn)程的時(shí)候,操作系統(tǒng)會(huì)為進(jìn)程分配資源,其中最主要的資源是內(nèi)存空間,因?yàn)槌绦蚴窃趦?nèi)存中運(yùn)行的。在進(jìn)程中,有些程序流程塊是可以亂序執(zhí)行的,并且這個(gè)代碼塊可以同時(shí)被多次執(zhí)行。實(shí)際上,這樣的代碼塊就是線程體。線程是進(jìn)程中亂序執(zhí)行的代碼流程。當(dāng)多個(gè)線程同時(shí)運(yùn)行的時(shí)候,這樣的執(zhí)行模式成為并發(fā)執(zhí)行。
多線程的目的是為了最大限度的利用CPU資源。
Java編寫程序都運(yùn)行在在Java虛擬機(jī)(JVM)中,在JVM的內(nèi)部,程序的多任務(wù)是通過(guò)線程來(lái)實(shí)現(xiàn)的。每用java命令啟動(dòng)一個(gè)java應(yīng)用程序,就會(huì)啟動(dòng)一個(gè)JVM進(jìn)程。在同一個(gè)JVM進(jìn)程中,有且只有一個(gè)進(jìn)程,就是它自己。在這個(gè)JVM環(huán)境中,所有程序代碼的運(yùn)行都是以線程來(lái)運(yùn)行。
一般常見的Java應(yīng)用程序都是單線程的。比如,用java命令運(yùn)行一個(gè)最簡(jiǎn)單的HelloWorld的Java應(yīng)用程序時(shí),就啟動(dòng)了一個(gè)JVM進(jìn)程,JVM找到程序程序的入口點(diǎn)main(),然后運(yùn)行main()方法,這樣就產(chǎn)生了一個(gè)線程,這個(gè)線程稱之為主線程。當(dāng)main方法結(jié)束后,主線程運(yùn)行完成。JVM進(jìn)程也隨即退出。
對(duì)于一個(gè)進(jìn)程中的多個(gè)線程來(lái)說(shuō),多個(gè)線程共享進(jìn)程的內(nèi)存塊,當(dāng)有新的線程產(chǎn)生的時(shí)候,操作系統(tǒng)不分配新的內(nèi)存,而是讓新線程共享原有的進(jìn)程塊的內(nèi)存。因此,線程間的通信很容易,速度也很快。不同的進(jìn)程因?yàn)樘幱诓煌膬?nèi)存塊,因此進(jìn)程之間的通信相對(duì)困難。
實(shí)際上,操作的系統(tǒng)的多進(jìn)程實(shí)現(xiàn)了多任務(wù)并發(fā)執(zhí)行,程序的多線程實(shí)現(xiàn)了進(jìn)程的并發(fā)執(zhí)行。多任務(wù)、多進(jìn)程、多線程的前提都是要求操作系統(tǒng)提供多任務(wù)、多進(jìn)程、多線程的支持。
在Java程序中,JVM負(fù)責(zé)線程的調(diào)度。線程調(diào)度是值按照特定的機(jī)制為多個(gè)線程分配CPU的使用權(quán)。調(diào)度的模式有兩種:分時(shí)調(diào)度和搶占式調(diào)度。分時(shí)調(diào)度是所有線程輪流獲得CPU使用權(quán),并平均分配每個(gè)線程占用CPU的時(shí)間;搶占式調(diào)度是根據(jù)線程的優(yōu)先級(jí)別來(lái)獲取CPU的使用權(quán)。JVM的線程調(diào)度模式采用了搶占式模式。
所謂的“并發(fā)執(zhí)行”、“同時(shí)”其實(shí)都不是真正意義上的“同時(shí)”。眾所周知,CPU都有個(gè)時(shí)鐘頻率,表示每秒中能執(zhí)行cpu指令的次數(shù)。在每個(gè)時(shí)鐘周期內(nèi),CPU實(shí)際上只能去執(zhí)行一條(也有可能多條)指令。操作系統(tǒng)將進(jìn)程線程進(jìn)行管理,輪流(沒(méi)有固定的順序)分配每個(gè)進(jìn)程很短的一段是時(shí)間(不一定是均分),然后在每個(gè)線程內(nèi)部,程序代碼自己處理該進(jìn)程內(nèi)部線程的時(shí)間分配,多個(gè)線程之間相互的切換去執(zhí)行,這個(gè)切換時(shí)間也是非常短的。因此多任務(wù)、多進(jìn)程、多線程都是操作系統(tǒng)給人的一種宏觀感受,從微觀角度看,程序的運(yùn)行是異步執(zhí)行的。
用一句話做總結(jié):雖然操作系統(tǒng)是多線程的,但CPU每一時(shí)刻只能做一件事,和人的大腦是一樣的,呵呵。
二、Java與多線程
Java語(yǔ)言的多線程需要操作系統(tǒng)的支持。
Java 虛擬機(jī)允許應(yīng)用程序并發(fā)地運(yùn)行多個(gè)執(zhí)行線程。Java語(yǔ)言提供了多線程編程的擴(kuò)展點(diǎn),并給出了功能強(qiáng)大的線程控制API。
在Java中,多線程的實(shí)現(xiàn)有兩種方式: 擴(kuò)展java.lang.Thread類 實(shí)現(xiàn)java.lang.Runnable接口
每個(gè)線程都有一個(gè)優(yōu)先級(jí),高優(yōu)先級(jí)線程的執(zhí)行優(yōu)先于低優(yōu)先級(jí)線程。每個(gè)線程都可以或不可以標(biāo)記為一個(gè)守護(hù)程序。當(dāng)某個(gè)線程中運(yùn)行的代碼創(chuàng)建一個(gè)新 Thread 對(duì)象時(shí),該新線程的初始優(yōu)先級(jí)被設(shè)定為創(chuàng)建線程的優(yōu)先級(jí),并且當(dāng)且僅當(dāng)創(chuàng)建線程是守護(hù)線程時(shí),新線程才是守護(hù)程序。
當(dāng) Java 虛擬機(jī)啟動(dòng)時(shí),通常都會(huì)有單個(gè)非守護(hù)線程(它通常會(huì)調(diào)用某個(gè)指定類的 main 方法)。Java 虛擬機(jī)會(huì)繼續(xù)執(zhí)行線程,直到下列任一情況出現(xiàn)時(shí)為止:
調(diào)用了 Runtime 類的 exit 方法,并且安全管理器允許退出操作發(fā)生。
非守護(hù)線程的所有線程都已停止運(yùn)行,無(wú)論是通過(guò)從對(duì) run 方法的調(diào)用中返回,還是通過(guò)拋出一個(gè)傳播到 run 方法之外的異常。
三、擴(kuò)展java.lang.Thread類
/** * File Name: TestMitiThread.java * Created by: IntelliJ IDEA.* Copyright: Copyright(c)2003-2006 * Company: Lavasoft([url]http://lavasoft.blog.51cto.com/[/url])* Author: leizhimin * Modifier: leizhimin * Date Time: 2007-5-17 10:03:12 * Readme: 通過(guò)擴(kuò)展Thread類實(shí)現(xiàn)多線程 */ public class TestMitiThread { public static void main(String[] rags){ System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行開始!”);new MitiSay(“A”).start();new MitiSay(“B”).start();System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行結(jié)束!”);} }
class MitiSay extends Thread { public MitiSay(String threadName){ super(threadName);}
public void run(){ System.out.println(getName()+ “ 線程運(yùn)行開始!”);for(int i = 0;i < 10;i++){ System.out.println(i + “ ” + getName());try { sleep((int)Math.random()* 10);} catch(InterruptedException e){ e.printStackTrace();} } System.out.println(getName()+ “ 線程運(yùn)行結(jié)束!”);} }
運(yùn)行結(jié)果:
main 線程運(yùn)行開始!main 線程運(yùn)行結(jié)束!A 線程運(yùn)行開始!0 A 1 A B 線程運(yùn)行開始!2 A 0 B 3 A 4 A 1 B 5 A 6 A 7 A 8 A 9 A A 線程運(yùn)行結(jié)束!2 B 3 B 4 B 5 B 6 B 7 B 8 B 9 B B 線程運(yùn)行結(jié)束!說(shuō)明:
程序啟動(dòng)運(yùn)行main時(shí)候,java虛擬機(jī)啟動(dòng)一個(gè)進(jìn)程,主線程main在main()調(diào)用時(shí)候被創(chuàng)建。隨著調(diào)用MitiSay的兩個(gè)對(duì)象的start方法,另外兩個(gè)線程也啟動(dòng)了,這樣,整個(gè)應(yīng)用就在多線程下運(yùn)行。
在一個(gè)方法中調(diào)用Thread.currentThread().getName()方法,可以獲取當(dāng)前線程的名字。在mian方法中調(diào)用該方法,獲取的是主線程的名字。
注意:start()方法的調(diào)用后并不是立即執(zhí)行多線程代碼,而是使得該線程變?yōu)榭蛇\(yùn)行態(tài)(Runnable),什么時(shí)候運(yùn)行是由操作系統(tǒng)決定的。
從程序運(yùn)行的結(jié)果可以發(fā)現(xiàn),多線程程序是亂序執(zhí)行。因此,只有亂序執(zhí)行的代碼才有必要設(shè)計(jì)為多線程。
Thread.sleep()方法調(diào)用目的是不讓當(dāng)前線程獨(dú)自霸占該進(jìn)程所獲取的CPU資源,以留出一定時(shí)間給其他線程執(zhí)行的機(jī)會(huì)。
實(shí)際上所有的多線程代碼執(zhí)行順序都是不確定的,每次執(zhí)行的結(jié)果都是隨機(jī)的。
四、實(shí)現(xiàn)java.lang.Runnable接口
/** * 通過(guò)實(shí)現(xiàn) Runnable 接口實(shí)現(xiàn)多線程 */ public class TestMitiThread1 implements Runnable {
public static void main(String[] args){ System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行開始!”);TestMitiThread1 test = new TestMitiThread1();Thread thread1 = new Thread(test);Thread thread2 = new Thread(test);thread1.start();thread2.start();System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行結(jié)束!”);}
public void run(){ System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行開始!”);for(int i = 0;i < 10;i++){ System.out.println(i + “ ” + Thread.currentThread().getName());try { Thread.sleep((int)Math.random()* 10);} catch(InterruptedException e){ e.printStackTrace();} } System.out.println(Thread.currentThread().getName()+ “ 線程運(yùn)行結(jié)束!”);} }
運(yùn)行結(jié)果:
main 線程運(yùn)行開始!Thread-0 線程運(yùn)行開始!main 線程運(yùn)行結(jié)束!0 Thread-0 Thread-1 線程運(yùn)行開始!0 Thread-1 1 Thread-1 1 Thread-0 2 Thread-0 2 Thread-1 3 Thread-0 3 Thread-1 4 Thread-0 4 Thread-1 5 Thread-0 6 Thread-0 5 Thread-1 7 Thread-0 8 Thread-0 6 Thread-1 9 Thread-0 7 Thread-1 Thread-0 線程運(yùn)行結(jié)束!8 Thread-1 9 Thread-1 Thread-1 線程運(yùn)行結(jié)束!說(shuō)明:
TestMitiThread1類通過(guò)實(shí)現(xiàn)Runnable接口,使得該類有了多線程類的特征。run()方法是多線程程序的一個(gè)約定。所有的多線程代碼都在run方法里面。Thread類實(shí)際上也是實(shí)現(xiàn)了Runnable接口的類。
在啟動(dòng)的多線程的時(shí)候,需要先通過(guò)Thread類的構(gòu)造方法Thread(Runnable target)構(gòu)造出對(duì)象,然后調(diào)用Thread對(duì)象的start()方法來(lái)運(yùn)行多線程代碼。
實(shí)際上所有的多線程代碼都是通過(guò)運(yùn)行Thread的start()方法來(lái)運(yùn)行的。因此,不管是擴(kuò)展Thread類還是實(shí)現(xiàn)Runnable接口來(lái)實(shí)現(xiàn)多線程,最終還是通過(guò)Thread的對(duì)象的API來(lái)控制線程的,熟悉Thread類的API是進(jìn)行多線程編程的基礎(chǔ)。
五、讀解Thread類API
static int MAX_PRIORITY 線程可以具有的最高優(yōu)先級(jí)。static int MIN_PRIORITY 線程可以具有的最低優(yōu)先級(jí)。static int NORM_PRIORITY 分配給線程的默認(rèn)優(yōu)先級(jí)。
構(gòu)造方法摘要
Thread(Runnable target)分配新的 Thread 對(duì)象。Thread(String name)分配新的 Thread 對(duì)象。
方法摘要
static Thread currentThread()返回對(duì)當(dāng)前正在執(zhí)行的線程對(duì)象的引用。ClassLoader getContextClassLoader()返回該線程的上下文 ClassLoader。long getId()返回該線程的標(biāo)識(shí)符。String getName()返回該線程的名稱。int getPriority()返回線程的優(yōu)先級(jí)。Thread.State getState()返回該線程的狀態(tài)。ThreadGroup getThreadGroup()返回該線程所屬的線程組。static boolean holdsLock(Object obj)當(dāng)且僅當(dāng)當(dāng)前線程在指定的對(duì)象上保持監(jiān)視器鎖時(shí),才返回 true。void interrupt()中斷線程。
static boolean interrupted()測(cè)試當(dāng)前線程是否已經(jīng)中斷。boolean isAlive()測(cè)試線程是否處于活動(dòng)狀態(tài)。boolean isDaemon()測(cè)試該線程是否為守護(hù)線程。boolean isInterrupted()測(cè)試線程是否已經(jīng)中斷。void join()等待該線程終止。void join(long millis)等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒。void join(long millis, int nanos)等待該線程終止的時(shí)間最長(zhǎng)為 millis 毫秒 + nanos 納秒。void resume()已過(guò)時(shí)。該方法只與 suspend()一起使用,但 suspend()已經(jīng)遭到反對(duì),因?yàn)樗哂兴梨i傾向。有關(guān)更多信息,請(qǐng)參閱為何 Thread.stop、Thread.suspend 和 Thread.resume 遭到反對(duì)?。void run()如果該線程是使用獨(dú)立的 Runnable 運(yùn)行對(duì)象構(gòu)造的,則調(diào)用該 Runnable 對(duì)象的 run 方法;否則,該方法不執(zhí)行任何操作并返回。void setContextClassLoader(ClassLoader cl)設(shè)置該線程的上下文 ClassLoader。void setDaemon(boolean on)將該線程標(biāo)記為守護(hù)線程或用戶線程。
static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)設(shè)置當(dāng)線程由于未捕獲到異常而突然終止,并且沒(méi)有為該線程定義其他處理程序時(shí)所調(diào)用的默認(rèn)處理程序。void setName(String name)改變線程名稱,使之與參數(shù) name 相同。void setPriority(int newPriority)更改線程的優(yōu)先級(jí)。
void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)設(shè)置該線程由于未捕獲到異常而突然終止時(shí)調(diào)用的處理程序。static void sleep(long millis)在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行)。static void sleep(long millis, int nanos)在指定的毫秒數(shù)加指定的納秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行)。void start()使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。void stop()已過(guò)時(shí)。該方法具有固有的不安全性。用 Thread.stop 來(lái)終止線程將釋放它已經(jīng)鎖定的所有監(jiān)視器(作為沿堆棧向上傳播的未檢查 ThreadDeath 異常的一個(gè)自然后果)。如果以前受這些監(jiān)視器保護(hù)的任何對(duì)象都處于一種不一致的狀態(tài),則損壞的對(duì)象將對(duì)其他線程可見,這有可能導(dǎo)致任意的行為。stop 的許多使用都應(yīng)由只修改某些變量以指示目標(biāo)線程應(yīng)該停止運(yùn)行的代碼來(lái)取代。目標(biāo)線程應(yīng)定期檢查該變量,并且如果該變量指示它要停止運(yùn)行,則從其運(yùn)行方法依次返回。如果目標(biāo)線程等待很長(zhǎng)時(shí)間(例如基于一個(gè)條件變量),則應(yīng)使用 interrupt 方法來(lái)中斷該等待。有關(guān)更多信息,請(qǐng)參閱《為何不贊成使用 Thread.stop、Thread.suspend 和 Thread.resume?》。void stop(Throwable obj)已過(guò)時(shí)。該方法具有固有的不安全性。請(qǐng)參閱 stop()以獲得詳細(xì)信息。該方法的附加危險(xiǎn)是它可用于生成目標(biāo)線程未準(zhǔn)備處理的異常(包括若沒(méi)有該方法該線程不太可能拋出的已檢查的異常)。有關(guān)更多信息,請(qǐng)參閱為何 Thread.stop、Thread.suspend 和 Thread.resume 遭到反對(duì)?。void suspend()已過(guò)時(shí)。該方法已經(jīng)遭到反對(duì),因?yàn)樗哂泄逃械乃梨i傾向。如果目標(biāo)線程掛起時(shí)在保護(hù)關(guān)鍵系統(tǒng)資源的監(jiān)視器上保持有鎖,則在目標(biāo)線程重新開始以前任何線程都不能訪問(wèn)該資源。如果重新開始目標(biāo)線程的線程想在調(diào)用 resume 之前鎖定該監(jiān)視器,則會(huì)發(fā)生死鎖。這類死鎖通常會(huì)證明自己是“凍結(jié)”的進(jìn)程。有關(guān)更多信息,請(qǐng)參閱為何 Thread.stop、Thread.suspend 和 Thread.resume 遭到反對(duì)?。String toString()返回該線程的字符串表示形式,包括線程名稱、優(yōu)先級(jí)和線程組。static void yield()暫停當(dāng)前正在執(zhí)行的線程對(duì)象,并執(zhí)行其他線程。
六、線程的狀態(tài)轉(zhuǎn)換圖
線程在一定條件下,狀態(tài)會(huì)發(fā)生變化。線程變化的狀態(tài)轉(zhuǎn)換圖如下:
1、新建狀態(tài)(New):新創(chuàng)建了一個(gè)線程對(duì)象。
2、就緒狀態(tài)(Runnable):線程對(duì)象創(chuàng)建后,其他線程調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中,變得可運(yùn)行,等待獲取CPU的使用權(quán)。
3、運(yùn)行狀態(tài)(Running):就緒狀態(tài)的線程獲取了CPU,執(zhí)行程序代碼。
4、阻塞狀態(tài)(Blocked):阻塞狀態(tài)是線程因?yàn)槟撤N原因放棄CPU使用權(quán),暫時(shí)停止運(yùn)行。直到線程進(jìn)入就緒狀態(tài),才有機(jī)會(huì)轉(zhuǎn)到運(yùn)行狀態(tài)。阻塞的情況分三種:
(一)、等待阻塞:運(yùn)行的線程執(zhí)行wait()方法,JVM會(huì)把該線程放入等待池中。
(二)、同步阻塞:運(yùn)行的線程在獲取對(duì)象的同步鎖時(shí),若該同步鎖被別的線程占用,則JVM會(huì)把該線程放入鎖池中。
(三)、其他阻塞:運(yùn)行的線程執(zhí)行sleep()或join()方法,或者發(fā)出了I/O請(qǐng)求時(shí),JVM會(huì)把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)、或者I/O處理完畢時(shí),線程重新轉(zhuǎn)入就緒狀態(tài)。
5、死亡狀態(tài)(Dead):線程執(zhí)行完了或者因異常退出了run()方法,該線程結(jié)束生命周期。
七、線程的調(diào)度
1、調(diào)整線程優(yōu)先級(jí):Java線程有優(yōu)先級(jí),優(yōu)先級(jí)高的線程會(huì)獲得較多的運(yùn)行機(jī)會(huì)。
Java線程的優(yōu)先級(jí)用整數(shù)表示,取值范圍是1~10,Thread類有以下三個(gè)靜態(tài)常量: static int MAX_PRIORITY 線程可以具有的最高優(yōu)先級(jí),取值為10。static int MIN_PRIORITY 線程可以具有的最低優(yōu)先級(jí),取值為1。static int NORM_PRIORITY 分配給線程的默認(rèn)優(yōu)先級(jí),取值為5。
Thread類的setPriority()和getPriority()方法分別用來(lái)設(shè)置和獲取線程的優(yōu)先級(jí)。
每個(gè)線程都有默認(rèn)的優(yōu)先級(jí)。主線程的默認(rèn)優(yōu)先級(jí)為Thread.NORM_PRIORITY。
線程的優(yōu)先級(jí)有繼承關(guān)系,比如A線程中創(chuàng)建了B線程,那么B將和A具有相同的優(yōu)先級(jí)。JVM提供了10個(gè)線程優(yōu)先級(jí),但與常見的操作系統(tǒng)都不能很好的映射。如果希望程序能移植到各個(gè)操作系統(tǒng)中,應(yīng)該僅僅使用Thread類有以下三個(gè)靜態(tài)常量作為優(yōu)先級(jí),這樣能保證同樣的優(yōu)先級(jí)采用了同樣的調(diào)度方式。
2、線程睡眠:Thread.sleep(long millis)方法,使線程轉(zhuǎn)到阻塞狀態(tài)。millis參數(shù)設(shè)定睡眠的時(shí)間,以毫秒為單位。當(dāng)睡眠結(jié)束后,就轉(zhuǎn)為就緒(Runnable)狀態(tài)。sleep()平臺(tái)移植性好。
3、線程等待:Object類中的wait()方法,導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify()方法或 notifyAll()喚醒方法。這個(gè)兩個(gè)喚醒方法也是Object類中的方法,行為等價(jià)于調(diào)用 wait(0)一樣。
4、線程讓步:Thread.yield()方法,暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把執(zhí)行機(jī)會(huì)讓給相同或者更高優(yōu)先級(jí)的線程。
5、線程加入:join()方法,等待其他線程終止。在當(dāng)前線程中調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),直到另一個(gè)進(jìn)程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài)。
6、線程喚醒:Object類中的notify()方法,喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果所有線程都在此對(duì)象上等待,則會(huì)選擇喚醒其中一個(gè)線程。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過(guò)調(diào)用其中一個(gè) wait 方法,在對(duì)象的監(jiān)視器上等待。直到當(dāng)前的線程放棄此對(duì)象上的鎖定,才能繼續(xù)執(zhí)行被喚醒的線程。被喚醒的線程將以常規(guī)方式與在該對(duì)象上主動(dòng)同步的其他所有線程進(jìn)行競(jìng)爭(zhēng);例如,喚醒的線程在作為鎖定此對(duì)象的下一個(gè)線程方面沒(méi)有可靠的特權(quán)或劣勢(shì)。類似的方法還有一個(gè)notifyAll(),喚醒在此對(duì)象監(jiān)視器上等待的所有線程。注意:Thread中suspend()和resume()兩個(gè)方法在JDK1.5中已經(jīng)廢除,不再介紹。因?yàn)橛兴梨i傾向。
7、常見線程名詞解釋
主線程:JVM調(diào)用程序mian()所產(chǎn)生的線程。
當(dāng)前線程:這個(gè)是容易混淆的概念。一般指通過(guò)Thread.currentThread()來(lái)獲取的進(jìn)程。后臺(tái)線程:指為其他線程提供服務(wù)的線程,也稱為守護(hù)線程。JVM的垃圾回收線程就是一個(gè)后臺(tái)線程。
前臺(tái)線程:是指接受后臺(tái)線程服務(wù)的線程,其實(shí)前臺(tái)后臺(tái)線程是聯(lián)系在一起,就像傀儡和幕后操縱者一樣的關(guān)系??苁乔芭_(tái)線程、幕后操縱者是后臺(tái)線程。由前臺(tái)線程創(chuàng)建的線程默認(rèn)也是前臺(tái)線程。可以通過(guò)isDaemon()和setDaemon()方法來(lái)判斷和設(shè)置一個(gè)線程是否為后臺(tái)線程。
本文出自 “熔 巖” 博客,請(qǐng)務(wù)必保留此出處http://lavasoft.blog.51cto.com/62575/27069
第三篇:JAVA基礎(chǔ)總結(jié)
JAVA基礎(chǔ)總結(jié)
轉(zhuǎn)眼間,已經(jīng)來(lái)到這里學(xué)習(xí)半年了,而現(xiàn)在我們對(duì)于JAVA學(xué)習(xí)才算是真正的開始。一開始接觸的時(shí)候我發(fā)現(xiàn)這個(gè)和C語(yǔ)言的基本語(yǔ)法幾乎一模一樣的,老師說(shuō):JAVA語(yǔ)言本來(lái)就是C++語(yǔ)言發(fā)展過(guò)來(lái)的,而C++是從C語(yǔ)言發(fā)展來(lái)的,C C++ 還有JAVA雖然是不同的三種語(yǔ)言,但是其實(shí)他們的基本語(yǔ)法是一樣的,但是它們卻有巨大的區(qū)別,這個(gè)區(qū)別主要是體現(xiàn)在思想上。
都說(shuō)C語(yǔ)言是面向過(guò)程的語(yǔ)言,C++ C#和JAVA是面向?qū)ο蟮木幊?,其?shí)就是思維方式稍微改了一下子,面向過(guò)程的語(yǔ)言主要是著重于算法,面向?qū)ο笾赜谶壿嫸选?/p>
這個(gè)教我們的老師是張成峰老師,張成峰是個(gè)很負(fù)責(zé)的老師,雖然JAVA基礎(chǔ)其實(shí)和C語(yǔ)言基礎(chǔ)差不多,但是仔細(xì)學(xué)學(xué)還是能找出很多不同的細(xì)節(jié)的,于是大家的問(wèn)題就很多,張老師幾乎就是手把手的教我們,所以整體來(lái)說(shuō)JAVA基礎(chǔ)學(xué)得挺扎實(shí)的。
我在這本書的學(xué)習(xí)不是挺好,聯(lián)系得少了,所以對(duì)代碼也不是特別熟悉。而且JAVA是一門重概念的書,對(duì)于我來(lái)說(shuō),概念是我的要害,理論知識(shí)也是我最怕學(xué)習(xí)的,所以學(xué)習(xí)這本書對(duì)我來(lái)說(shuō)很是艱難,聽了很久的課,代碼寫得出來(lái),但是理論知識(shí)幾乎一點(diǎn)也不明白,結(jié)果就造成了這次筆試考的不好。
筆試考的不好,機(jī)試也因?yàn)槲业拇中臎](méi)有考好,所以這次的成績(jī)不好。
學(xué)習(xí)JAVA基礎(chǔ)后,還要在學(xué)習(xí)的過(guò)程中對(duì)每個(gè)知識(shí)都要用心和細(xì)心,當(dāng)然最該注重的地方就是應(yīng)該提高我對(duì)理論知識(shí)的學(xué)習(xí),要多看書,也要多敲敲代碼,這些就是提高學(xué)習(xí)知識(shí)全面的方法。
下一本書學(xué)習(xí)的是JAVAOO算是JAVA的一個(gè)重要的內(nèi)容了,這才會(huì)真正的接觸JAVA的核心課程,在這本書里我要好好的理解理論知識(shí),仔細(xì)的學(xué)習(xí)每個(gè)知識(shí)。
第四篇:Java基礎(chǔ)總結(jié)
? 基本數(shù)據(jù)類型
? 變量單元直接存放數(shù)據(jù)
? 賦值和傳參的方式:傳值,即傳遞副本
? 比較相等使用關(guān)系運(yùn)算符“==”
? 引用數(shù)據(jù)類型
? 變量單元存放引用即對(duì)象地址,而數(shù)據(jù)(對(duì)象)在另一內(nèi)存區(qū)域存放。
? 賦值和傳參的方式:傳引用(傳遞對(duì)象的地址),即傳遞對(duì)象本身。
? 使用關(guān)系運(yùn)算符“==”比較兩個(gè)引用類型變量,比較的是地址,如果比較結(jié)果為
真,說(shuō)明兩個(gè)變量引用了同一對(duì)象。
? 比較兩個(gè)對(duì)象是否相等應(yīng)使用equals方法
? Java是面向?qū)ο蟮恼Z(yǔ)言,開發(fā)Java程序就是開發(fā)Java類,Java的變量定義、方法(函
數(shù))和語(yǔ)句都必須在類中書寫,“無(wú)類即無(wú)Java”。
? 類的實(shí)例成員
屬性(成員變量):直接定義在類體中的變量(注:在方法或語(yǔ)句塊中定義的變量不是屬性)
方法:直接定義在類體中的方法。
類成員:直接定義在類體中的內(nèi)部類,即類成員。
注:對(duì)象的成員是從屬于對(duì)象的,必須通過(guò)對(duì)象訪問(wèn),在Java中不存在脫離對(duì)象和類而獨(dú)立存在的屬性和方法。
? 類、方法、語(yǔ)句三者的關(guān)系:
類中包含方法,方法中包含語(yǔ)句;方法中不能嵌套方法;語(yǔ)句不能直接寫在類體中。
? 變量的作用域
? 局部變量-方法的參數(shù)、方法體中定義的變量、語(yǔ)句塊中定義的變量,僅在所定義的方法體或語(yǔ)句塊中有效。
? 屬性-在整個(gè)類體中有效。
? 公有的屬性-其它類可以本類對(duì)象訪問(wèn)。
? 私有的屬性-僅限本類內(nèi)訪問(wèn)
? 局部變量(無(wú)論基本類型還是引用類型)在棧內(nèi)存中,對(duì)象在堆內(nèi)存中。注:引用類型的局部變量?jī)?nèi)存放是對(duì)象的引用(即地址),而對(duì)象在堆內(nèi)存中。
? 方法的重載-在同一類中多個(gè)方法同名的語(yǔ)法現(xiàn)象,方法重載應(yīng)符合以下條件:
? 方法同名
? 參數(shù)有所不同(即類型、個(gè)數(shù)和順序三者至少有一個(gè)不同)
注:方法是否重載不考慮返回類型等其它方面。
? 包和訪問(wèn)修飾符
? 包-類的目錄結(jié)構(gòu),主要用途是方便類的管理。
? 類的簡(jiǎn)稱:不含包名的類名
? 類的全限定名稱(類的全稱):帶包名的類名。
? 訪問(wèn)修飾符
? private-僅限本類內(nèi)訪問(wèn)
? public-任何類都能夠訪問(wèn)
? 默認(rèn)-限本包的類訪問(wèn)
? protected--限本包的類訪問(wèn)和子類的訪問(wèn)
? 類的成員(屬性、方法和成員內(nèi)部類)可以使用四種訪問(wèn)修飾符,頂級(jí)外部類僅能
使用public和默認(rèn)兩種修飾符。
? 數(shù)組
? 基本類型的數(shù)組的元素放的是數(shù)據(jù)
? 對(duì)象數(shù)據(jù)的元素放的是對(duì)象的引用
? 二維數(shù)組實(shí)際上是一個(gè)維數(shù)組,而其每個(gè)元素又是一個(gè)一維數(shù)組。
? 構(gòu)造方法-與類名同名并且無(wú)返回類型的方法
? 構(gòu)造方法的作用是創(chuàng)建對(duì)象,僅能通過(guò)new關(guān)鍵字調(diào)用。
? 類中未顯式定義構(gòu)造方法時(shí),類中會(huì)有默認(rèn)的構(gòu)造方法(即一個(gè)public、無(wú)參的構(gòu)
造方法);類中一旦定義顯式定義構(gòu)造方法,將不再產(chǎn)生默認(rèn)的構(gòu)造方法。
? 構(gòu)造方法可以重載
? 構(gòu)造方法只能可以使用四個(gè)訪問(wèn)修飾符,不可以使用其它修飾符(如static、final
等)。
? this關(guān)鍵字
? this表示本對(duì)象或?qū)ο笞陨淼囊?/p>
? 通過(guò)this可以調(diào)用本類的成員方法和屬性
? 通過(guò)this可以調(diào)用本類的構(gòu)造方法,this調(diào)用構(gòu)造方法的語(yǔ)句必須寫在構(gòu)造方法的第一句。
? 實(shí)例成員和靜態(tài)成員
? 類的成員(屬性、方法和成員類)可劃分為靜態(tài)成員和實(shí)例成員。
? 實(shí)例成員是屬于對(duì)象的,隨著對(duì)象的創(chuàng)建而存在,隨著對(duì)象的銷毀而銷毀。? 靜態(tài)成員是屬于類的,隨著類的加載而存在,隨著類的銷毀而銷毀。
? 使用static修飾的成員是靜態(tài)成員,未使用static修飾的成員是實(shí)例成員。? 靜態(tài)成員內(nèi)不能使用this關(guān)鍵字。
? this表示當(dāng)前對(duì)象的引用。
? 對(duì)象的初始化
? 第一:實(shí)例屬性賦默認(rèn)值
? 第二:實(shí)例屬性賦初值
? 第三:執(zhí)行對(duì)象初始化塊
? 第四:執(zhí)行構(gòu)造方法
? 類的初始化
? 第一:靜態(tài)屬性賦默認(rèn)值
? 第二:靜態(tài)屬性賦初值
? 第三:執(zhí)行靜態(tài)塊
? 繼承的基本概念
? Java僅支持單繼承
?
?
?
?
? ? 如果一個(gè)類沒(méi)有顯式繼承任何類,則隱式繼承java.lang.Object類 ? 子類擁有父類的一切,子類對(duì)象由兩部分構(gòu)成:父類對(duì)象部分和子類個(gè)性化的部分。? 子類并不能訪問(wèn)父類的一切: ? 子類可以訪問(wèn)父類的public成員和protected成員 ? 子類不可以訪問(wèn)父類的private成員 ? 僅當(dāng)子類與父類同在一包時(shí),子類方可以訪問(wèn)父類的默認(rèn)訪問(wèn)控制的成員。繼承與類和對(duì)象的初始化 ? 構(gòu)造子類對(duì)象時(shí),首先構(gòu)造父類對(duì)象,其次構(gòu)造子類個(gè)性化部分,兩者共同構(gòu)成完整的子類對(duì)象,即首先進(jìn)行父類對(duì)象的初始化,在初始化子類對(duì)象(個(gè)性化)部分。? 子類構(gòu)造方法的執(zhí)行首先調(diào)用父類的構(gòu)造方法。? 若在子類構(gòu)造方法中無(wú)顯式調(diào)用父類構(gòu)造方法的語(yǔ)句,則系統(tǒng)默認(rèn)調(diào)用父類中可訪問(wèn)的無(wú)參的構(gòu)造方法,如果這時(shí)候父類中恰好沒(méi)有這樣的構(gòu)造方法,則編譯出錯(cuò)。? 在子類的構(gòu)造方法中可以通過(guò)super關(guān)鍵字調(diào)用父類構(gòu)造方法。這樣的調(diào)用語(yǔ)句只能出現(xiàn)在子類構(gòu)造方法的第一句。? 關(guān)于初始化的順序 ? 初始化父類 ? 初始化子類 ? 初始化父類對(duì)象 ? 初始化子類對(duì)象 繼承與類型轉(zhuǎn)換 ? 子類型對(duì)象可以自動(dòng)轉(zhuǎn)型為父類型 ? 父類型引用某個(gè)子類型對(duì)象時(shí),可以強(qiáng)制轉(zhuǎn)化為這個(gè)具體的子類型 方法重寫 ? 在繼承的情況下,子類的實(shí)例方法與父類的實(shí)例方法的方法名稱、參數(shù)、返回類型、throws聲明完全一致,并且該子類方法的訪問(wèn)權(quán)限不低于父類方法的訪問(wèn)權(quán)限,即方法重寫(子類方法重寫了父類方法),也稱方法覆蓋。? 方法重寫僅存在于父子類中的實(shí)例方法,靜態(tài)方法沒(méi)有重寫的概念。? 當(dāng)通過(guò)子類型對(duì)象執(zhí)行重寫方法時(shí),將始終表現(xiàn)為子類的行為,而且無(wú)論引用對(duì)象的變量是父類型還是子類型,也無(wú)論是直接調(diào)用還是通過(guò)父類型其它方法間接調(diào)用,都將如此。? final修飾的方法不可以被重寫 ? final修飾的類不可以被繼承 隱藏成員變量 ? 如果子類和父類中定義了同名稱的成員變量,則稱子類隱藏了父類的成員變量 ? 通過(guò)父類方法訪問(wèn)隱藏的成員變量時(shí),將獲得父類成員變量 ? 通過(guò)子類方法訪問(wèn)隱藏的成員變量時(shí),將獲得子類成員變量 ? 通過(guò)父類型的引用直接訪問(wèn)隱藏的成員變量時(shí),將獲得父類成員變量 ? 通過(guò)子類型的引用直接訪問(wèn)隱藏的成員變量時(shí),將獲得子類成員變量 super關(guān)鍵字
? super僅能用于子類中表示本對(duì)象的父對(duì)象部分
? super可以調(diào)用父類型的構(gòu)造方法
? Super可以調(diào)用父類的成員
? Super不可以使用在靜態(tài)上下文中
? Super不可以做為參數(shù)傳遞,不可以做為返回值返回。
? 當(dāng)方法重寫時(shí),或父類成員變量被隱藏時(shí),子類中只能通過(guò)super訪問(wèn)父類方法和
父類成員變量
? final關(guān)鍵字
? 用于變量,表示變量的值不可改變
? 用于類,表示類不可被繼承
? 用于方法,表示方法不可以被重寫
? 關(guān)于final變量的初始化時(shí)機(jī)
? 局部變量:聲明的時(shí)候初始化
? 實(shí)例成員變量:聲明、對(duì)象初始化塊和構(gòu)造方法三處之一
? 靜態(tài)成員變量:聲明、靜態(tài)塊兩處之一
? 抽象類
? 抽象類可以包含抽象方法,也可以不包含抽象方法
? 含有抽象方法的類必須定義為抽象類
? 抽象類有構(gòu)造方法
? 抽象類不能夠?qū)嵗?/p>
? 通過(guò)抽象類可以調(diào)用其靜態(tài)成員
? 抽象類是需要由子類繼承的,因此抽象類不允許是final類
? 抽象方法
? 抽象方法沒(méi)有方法體,包括一對(duì)空的大括號(hào)也不允許有
? 抽象方法必須是實(shí)例方法,抽象方法不允許是final的? 抽象類與繼承
? 抽象類可以被繼承
? 若抽象類的子類是非抽象類,則該子類必須實(shí)現(xiàn)(重寫)其父類的所有抽象方法 ? 若抽象類的子類也是抽象類,則該子類可以不實(shí)現(xiàn)(重寫)其父類的全部或部分抽象
方法。
? 接口
? 接口也是數(shù)據(jù)類型,可以將其理解為“純”抽象類
? 接口不是類,也沒(méi)有構(gòu)造方法,不能夠?qū)嵗?/p>
? 接口中的屬性一律是public、static、final的,并可以省略這三個(gè)關(guān)鍵字
? 接口的方法一律是public、abstract的,并且可以省略這兩個(gè)關(guān)鍵字
? 接口中可以不包含任何屬性和方法
? 接口與實(shí)現(xiàn)
? 接口不是類,因此接口與類的關(guān)系不是“繼承”關(guān)系,而是“實(shí)現(xiàn)”關(guān)系,我們可
以將實(shí)現(xiàn)理解為繼承(盡管這并不恰當(dāng))
? 如果接口的實(shí)現(xiàn)類是抽象類,則該實(shí)現(xiàn)類可以不實(shí)現(xiàn)接口的全部或部分方法 ? 如果接口的實(shí)現(xiàn)類是非抽象類,則該實(shí)現(xiàn)類必須實(shí)現(xiàn)接口的全部方法
? 一個(gè)類可以實(shí)現(xiàn)多個(gè)接口
? 接口與繼承
? 接口之間可以相互繼承
? 一個(gè)接口可以繼承多個(gè)接口
? 接口與類型轉(zhuǎn)換
? 接口的的子類型對(duì)象可以自動(dòng)向上轉(zhuǎn)型為接口類型
? 接口的子類型指:是接口的實(shí)現(xiàn)類或者接口的子接口
? 如果變量引用的對(duì)象實(shí)際是某個(gè)接口的實(shí)現(xiàn)類對(duì)象,而變量的類型不是這個(gè)接口的子類型,那么則可以強(qiáng)制轉(zhuǎn)換為這個(gè)接口類型。
? 異常的類層次結(jié)構(gòu)
? Throwable錯(cuò)誤類,表示不可恢復(fù)的致命錯(cuò)誤
? Exception運(yùn)行時(shí)異常,此類異常可以不做顯式處理
? 非運(yùn)行時(shí)異常catch
? 聲明拋出 在方法頭通過(guò)throws聲明可能拋出的異常類型
? 異常機(jī)制的五個(gè)關(guān)鍵字
? try catch finally throw throws
? 如何使用
? try-catch
? try-catch-finally注:只要try執(zhí)行,其對(duì)應(yīng)的finally塊才必然執(zhí)行
? try-finally注:只要try執(zhí)行,其對(duì)應(yīng)的finally塊才必然執(zhí)行
? throw 主動(dòng)拋出一個(gè)異常
? throws 用在方法聲明頭部,聲明方法可能拋出異常
? finally代碼塊多用于書寫資源回收代碼
? Java集合類(集合框架)
? Collection接口
? List接口 允許重復(fù)元素,元素有索引序號(hào),并按放入元素的次序編號(hào)
? ArrayList 線性表結(jié)構(gòu),查找快,增刪慢
? LinkedList 鏈表結(jié)構(gòu),查找慢,增刪快
? Vector 同步,查找、增刪性能都不高。
? Set接口 不允許重復(fù)元素,元素?zé)o索引編號(hào)
? HashSet 元素散列存放
? TreeSet元素按自然順序排序(即從小到大排序)
? Map接口
? HashMap
? 允許null值和null鍵
? 不同步
? Hashtable <--Properties
? 不允許null值和null鍵
? 同步
? 內(nèi)部類
第五篇:多核多線程題目總結(jié)
2.并行和并發(fā)的概念與區(qū)別:
-如果某個(gè)系統(tǒng)支持兩個(gè)或多個(gè)動(dòng)作(Action)同時(shí)存在,那么這個(gè)系統(tǒng)就是一個(gè)并發(fā)系統(tǒng)-如果某個(gè)系統(tǒng)支持兩個(gè)或多個(gè)動(dòng)作同時(shí)執(zhí)行,那么這個(gè)系統(tǒng)就是一個(gè)并行系統(tǒng)
-并發(fā)程序可同時(shí)擁有兩個(gè)或多個(gè)線程。如果程序能夠并行執(zhí)行,則一定是運(yùn)行在多核處理器上,每個(gè)線程都將分配到一個(gè)獨(dú)立的處理器核上。
-“并行”概念是“并發(fā)”概念的一個(gè)子集 3.并行計(jì)算技術(shù)的主要目的:
加速求解問(wèn)題的速度
例如,給定某應(yīng)用,在單處理器上,串行執(zhí)行需要2 周,這個(gè)速度對(duì)一般的應(yīng)用而言,是無(wú)法忍受的。于是,可以借助并行計(jì)算,使用100 臺(tái)處理器,加速50 倍,將執(zhí)行時(shí)間縮短為6.72 個(gè)小時(shí)。
提高求解問(wèn)題的規(guī)模
例如,在單處理器上,受內(nèi)存資源2GB的限制,只能計(jì)算10 萬(wàn)個(gè)網(wǎng)格,但是,當(dāng)前數(shù)值模擬要求計(jì)算千萬(wàn)個(gè)網(wǎng)格。于是,也可以借助并行計(jì)算,使用100 個(gè)處理器,將問(wèn)題求解規(guī)模線性地?cái)U(kuò)大100 倍。并行計(jì)算的主要目標(biāo):
在并行機(jī)上,解決具有重大挑戰(zhàn)性計(jì)算任務(wù)的科學(xué)、工程及商業(yè)計(jì)算問(wèn)題,滿足不斷增長(zhǎng)的應(yīng)用問(wèn)題對(duì)速度和內(nèi)存資源的需求。
4.并行計(jì)算的主要研究?jī)?nèi)容大致可分為四個(gè)方面:
并行機(jī)的高性能特征抽取
充分理解和抽取當(dāng)前并行機(jī)體系結(jié)構(gòu)的高性能特征,提出實(shí)用的并行計(jì)算模型和并行性能評(píng)價(jià)方法,指導(dǎo)并行算法的設(shè)計(jì)和并行程序的實(shí)現(xiàn)。
并行算法設(shè)計(jì)與分析
設(shè)計(jì)高效率的并行算法,將應(yīng)用問(wèn)題分解為可并行計(jì)算的多個(gè)子任務(wù),并具體分析這些算法的可行性和效果。
并行實(shí)現(xiàn)技術(shù)
主要包含并行程序設(shè)計(jì)和并行性能優(yōu)化。
并行應(yīng)用
這是并行計(jì)算研究的最終目的。通過(guò)驗(yàn)證和確認(rèn)并行程序的正確性和效率,進(jìn)一步將程序發(fā)展為并行應(yīng)用軟件,應(yīng)用于求解實(shí)際問(wèn)題。同時(shí),結(jié)合實(shí)際應(yīng)用出現(xiàn)的各種問(wèn)題,不斷地改進(jìn)并行算法和并行程序。5.并行程序執(zhí)行時(shí)間
對(duì)各個(gè)進(jìn)程,墻上時(shí)間可進(jìn)一步分解為計(jì)算CPU時(shí)間、通信CPU時(shí)間、同步開銷時(shí)間、同步導(dǎo)致的進(jìn)程空閑時(shí)間
計(jì)算CPU時(shí)間:進(jìn)程指令執(zhí)行所花費(fèi)的CPU時(shí)間,包括程序本身的指令執(zhí)行占用的時(shí)間(用戶時(shí)間)和系統(tǒng)指令花費(fèi)的時(shí)間;
通信CPU時(shí)間:進(jìn)程通信花費(fèi)的CPU時(shí)間; 同步開銷時(shí)間:進(jìn)程同步花費(fèi)的時(shí)間;
進(jìn)程空閑時(shí)間:進(jìn)程空閑時(shí)間是指并行程序執(zhí)行過(guò)程中,進(jìn)程所有空閑時(shí)間總和(如進(jìn)程阻塞式等待其他進(jìn)程的消息時(shí)。此時(shí)CPU通常是空閑的,或者處于等待狀態(tài))6.并行程序性能優(yōu)化
最主要的是選擇好的并行算法和通信模式
減少通信量、提高通信粒度
提高通信粒度的有效方法就是減少通信次數(shù),盡可能將可以一次傳遞的數(shù)據(jù)合并起來(lái)一起傳遞
全局通信盡量利用高效集合通信算法
對(duì)于標(biāo)準(zhǔn)的集合通信,如廣播、規(guī)約、數(shù)據(jù)散發(fā)與收集等,盡量調(diào)用MPI標(biāo)準(zhǔn)庫(kù)函數(shù) 挖掘算法的并行度,減少CPU空閑等待
具有數(shù)據(jù)相關(guān)性的計(jì)算過(guò)程會(huì)導(dǎo)致并行運(yùn)行的部分進(jìn)程空閑等待.在這種情況下,可以考慮改變算法來(lái)消除數(shù)據(jù)相關(guān)性
7.順序程序的特性
順序性:處理機(jī)嚴(yán)格按照指令次序依次執(zhí)行,即僅當(dāng)一條指令執(zhí)行完后才開始執(zhí)行下一條指令;
封閉性:程序在執(zhí)行過(guò)程中獨(dú)占系統(tǒng)中的全部資源,該程序的運(yùn)行環(huán)境只與其自身動(dòng)作有關(guān),不受其它程序及外界因素影響;
可再現(xiàn)性:程序的執(zhí)行結(jié)果與執(zhí)行速度無(wú)關(guān),而只與初始條件有關(guān),給定相同的初始條件,程序的任意多次執(zhí)行一定得到相同的執(zhí)行結(jié)果.8.并發(fā)程序特性
交叉性:程序并發(fā)執(zhí)行對(duì)應(yīng)某一種交叉,不同的交叉可能導(dǎo)致不同的計(jì)算結(jié)果,操作系統(tǒng)應(yīng)當(dāng)保證只產(chǎn)生導(dǎo)致正確結(jié)果的交叉,去除那些可能導(dǎo)致不正確結(jié)果的交叉;
非封閉性:一個(gè)進(jìn)程的運(yùn)行環(huán)境可能被其它進(jìn)程所改變,從而相互影響;
不可再現(xiàn)性:由于交叉的隨機(jī)性,并發(fā)程序的多次執(zhí)行可能對(duì)應(yīng)不同的交叉,因而不能期望重新運(yùn)行的程序能夠再現(xiàn)上次運(yùn)行的結(jié)果。
10.Win32線程同步的實(shí)現(xiàn)
11.數(shù)據(jù)作用域?qū)?shù)據(jù)值的影響
12.分析程序的結(jié)果
13.并行區(qū)域編程與parallel for語(yǔ)句的區(qū)別
-并行區(qū)域采用了復(fù)制執(zhí)行方式,將代碼在所有的線程內(nèi)各執(zhí)行一次;
-循環(huán)并行化則是采用工作分配執(zhí)行方式,將循環(huán)需做的所有工作量,按一定的方式分配給各個(gè)執(zhí)行線程,全部線程執(zhí)行工作的總合等于原先串行執(zhí)行所完成的工作量。14.OpenMP提供三種不同的互斥鎖機(jī)制: 臨界區(qū)(critical)原子操作(atomic)由庫(kù)函數(shù)來(lái)提供同步操作 int counter=0;#pragma omp parallel {
for(int i=0;i<10000;i++)
#pragma omp atomic //atomic operation
}
printf(“counter = %dn”,counter);
counter=20000 25.影響性能的主要因素
并行化代碼在應(yīng)用程序中的比率-OpenMP 本身的開銷
-OpenMP 獲得應(yīng)用程序多線程并行化的能力,需要一定的程序庫(kù)支持。在這些庫(kù)程序?qū)Τ绦虿⑿屑铀俚耐瑫r(shí)也需要運(yùn)行庫(kù)本身-負(fù)載均衡
-局部性
在程序運(yùn)行過(guò)程中,高速緩存將緩存最近剛剛訪問(wèn)過(guò)的數(shù)據(jù)及其相鄰的數(shù)據(jù)。因此,在編寫程序的時(shí)候,需要考慮到高速緩存的作用,有意地運(yùn)用這種局部性帶來(lái)的高速緩存的效率提高。-線程同步帶來(lái)的開銷
多個(gè)線程在進(jìn)行同步的時(shí)候必然帶來(lái)一定的同步開銷,在使用多線程進(jìn)行開發(fā)時(shí)需要考慮同步的必要性,消除不必要的同步,或者調(diào)整同步的順序,就有可能帶來(lái)性能上的提升。26.什么是MPI 消息傳遞接口(Message Passing Interface,簡(jiǎn)稱MPI)是一種編程接口標(biāo)準(zhǔn),而不是一種具體的編程語(yǔ)言?;竞x:MPI標(biāo)準(zhǔn)定義了一組具有可移植性的編程接口。
特征:
1、典型的實(shí)現(xiàn)包括開源的MPICH、LAM MPI以及不開源的INTEL MPI。
2、程序員設(shè)計(jì)好應(yīng)用程序并行算法,調(diào)用這些接口,鏈接相應(yīng)平臺(tái)上的MPI庫(kù),即可實(shí)現(xiàn)基于消息傳遞的并行計(jì)算
27.MPICH的安裝和配置 counter++;
28.MPI程序的四個(gè)基本函數(shù)-MPI_Init和MPI_Finalize MPI_Init初始化MPI執(zhí)行環(huán)境,建立多個(gè)MPI進(jìn)程之間的聯(lián)系,為后續(xù)通信做準(zhǔn)備。而MPI_Finalize則是結(jié)束MPI執(zhí)行環(huán)境。這兩個(gè)函數(shù)用來(lái)定義MPI程序的并行區(qū)-MPI_Comm_rank
用來(lái)標(biāo)識(shí)各個(gè)MPI進(jìn)程,兩個(gè)函數(shù)參數(shù):
MPI_Comm類型的通信域,表示參與計(jì)算的MPI進(jìn)程組 &rank,返回調(diào)用進(jìn)程在comm中的標(biāo)識(shí)號(hào)-MPI_Comm_size 用來(lái)標(biāo)識(shí)相應(yīng)進(jìn)程組中有多少個(gè)進(jìn)程,有兩個(gè)參數(shù): MPI_Comm類型的通信域,標(biāo)尺參與計(jì)算的MPI進(jìn)程組 整型指針,返回相應(yīng)進(jìn)程組中的進(jìn)程數(shù)
29.MPI的點(diǎn)對(duì)點(diǎn)通信
兩個(gè)最重要的MPI函數(shù)MPI_Send和MPI_Recv。
-int MPI_SEND(buf, count, datatype, dest, tag, comm)這個(gè)函數(shù)的含義是向通信域comm中的dest進(jìn)程發(fā)送數(shù)據(jù)。消息數(shù)據(jù)存放在buf中,類型是datatype,個(gè)數(shù)是count個(gè)。這個(gè)消息的標(biāo)志是tag,用以和本進(jìn)程向同一目的進(jìn)程發(fā)送的其他消息區(qū)別開來(lái)。
-int MPI_RECV(buf,count,datatype,source,tag,comm,status)MPI_Recv絕大多數(shù)的參數(shù)和MPI_Send相對(duì)應(yīng),有相同的意義。唯一的區(qū)別就是MPI_Recv里面多了一個(gè)參數(shù)status。status主要顯示接收函數(shù)的各種錯(cuò)誤狀態(tài)。30.消息管理7要素 發(fā)送或者接收緩沖區(qū)buf; 數(shù)據(jù)數(shù)量count; 數(shù)據(jù)類型datatype;
目標(biāo)進(jìn)程或者源進(jìn)程destination/source; 消息標(biāo)簽tag; 通信域comm;.消息狀態(tài)status,只在接收的函數(shù)中出現(xiàn)。31.MPI群集通信
群集通信是包含了一對(duì)多、多對(duì)一和多對(duì)多的進(jìn)程通信模式。其最大特點(diǎn)是多個(gè)進(jìn)程參與通信。常用的MPI群集通信函數(shù): 同步
廣播 聚集 播撒