久久99精品久久久久久琪琪,久久人人爽人人爽人人片亞洲,熟妇人妻无码中文字幕,亚洲精品无码久久久久久久

實驗06 線程應(yīng)用及線程并發(fā)庫

時間:2019-05-12 15:21:56下載本文作者:會員上傳
簡介:寫寫幫文庫小編為你整理了多篇相關(guān)的《實驗06 線程應(yīng)用及線程并發(fā)庫》,但愿對你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫還可以找到更多《實驗06 線程應(yīng)用及線程并發(fā)庫》。

第一篇:實驗06 線程應(yīng)用及線程并發(fā)庫

實驗六 線程應(yīng)用及線程并發(fā)庫

1.實驗內(nèi)容

實驗題1編寫一程序,實現(xiàn)如下功能:子線程循環(huán)10次,接著主線程循環(huán)100次,接著又回到子線程循環(huán)10次,主線程循環(huán)100次,如此循環(huán)50次。package cn.jp.me;

public class ManageProcedure {

public synchronized void addMainProcedure(){

if(shouldBeSub){ try { wait();

} } for(int i = 1;i <= subTimes;++i){ } shouldBeSub = false;notify();System.out.println(“SubProcedure ” + i);} public synchronized void addSubProcedure(){

if(!shouldBeSub){

try { wait();public ManageProcedure(int subTimes, int mainTimes){

} shouldBeSub = true;this.subTimes = subTimes;this.mainTimes = mainTimes;private boolean shouldBeSub;private int subTimes, mainTimes;} catch(InterruptedException e){

}

} catch(InterruptedException e){

} } } for(int i = 1;i <= mainTimes;++i){ } shouldBeSub = true;notify();System.out.println(“MainProcedure ” + i);package cn.jp.me;

public class SingleProcedure implements Runnable {

@Override public void run(){

if(type.equals(“sub”)){

for(int i = 0;i < times;++i){ } manageProcedure.addSubProcedure();public SingleProcedure(int times, String type,} ManageProcedure manageProcedure){ private int times;private String type;private ManageProcedure manageProcedure;this.times = times;this.type = type;this.manageProcedure = manageProcedure;} else {

for(int i = 0;i < times;++i){ } manageProcedure.addMainProcedure();

} } } package cn.jp.me;

import java.util.Scanner;

public class Text {

} } subThread.start();mainThread.start();Thread subThread = new Thread(subProcedure);Thread mainThread = new Thread(mainProcedure);

ManageProcedure manageProcedure = new ManageProcedure(subTimes, mainTimes);public static void main(String[] args){

int subTimes, mainTimes, totalTimes;Scanner scanner = new Scanner(System.in);System.out.println(“Please Input The SubTimes && MainTimes && The Total Times”);subTimes = scanner.nextInt();mainTimes = scanner.nextInt();totalTimes = scanner.nextInt();SingleProcedure subProcedure = new SingleProcedure(totalTimes, “sub”, manageProcedure);SingleProcedure mainProcedure = new SingleProcedure(totalTimes, “main”, manageProcedure);

實驗題2 設(shè)計4個線程,其中2個線程每次對count增加1,另外兩個線程每次對count減1。

package cn.jp.me;

public class SingleProcedure implements Runnable {

public synchronized void run(){

if(type.equals(“Add”)){ for(int i = 0;i < times;++i){ manageProcedure.add();public SingleProcedure(int runTimes, String typeString,} ManageProcedure manageProcedure){ this.times = runTimes;type = typeString;this.manageProcedure = manageProcedure;private int times;private String type;private ManageProcedure manageProcedure;

}

}

} } for(int i = 0;i < times;++i){ } manageProcedure.substract();} else { package cn.jp.me;public class ManageProcedure {

} package cn.jp.me.text;

import cn.jp.me.ManageProcedure;import cn.jp.jme.SingleProcedure;

public class Text {

Thread addOne = new Thread(singleAdd);public static void main(String[] args){

ManageProcedure manageProcedure = new ManageProcedure();SingleProcedure singleAdd = new SingleProcedure(100 / 2, “Add”, manageProcedure);100 / 2, “substract”, manageProcedure);SingleProcedure singleSubstract = new SingleProcedure(public int getCount(){ } return count;public synchronized void substract(){

}--count;System.out.println(“Thread ” + Thread.currentThread().getName()+ “The Count : ” + getCount());public synchronized void add(){

} ++count;System.out.println(“Thread ” + Thread.currentThread().getName()+ “The Count : ” + getCount());public ManageProcedure(){ } count = 0;private int count;

}

} addOne.setName(“Add One Thread”);Thread addTwo = new Thread(singleAdd);addTwo.setName(“Add Two Thread”);Thread substractOne = new Thread(singleSubstract);substractOne.setName(“Substract One Thread”);Thread substractTwo = new Thread(singleSubstract);substractTwo.setName(“Substract Two Thread”);addOne.start();addTwo.start();substractOne.start();substractTwo.start();

實驗題3 CyclicBarrier是一個同步輔助類,它允許一組線程互相等待,直到到達(dá)某個公共屏障點。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待,此時 CyclicBarrier 很有用。因為該 barrier 在釋放等待線程后可以重用,所以稱它為循環(huán)的 barrier。

題目要求:

(1)要在公司大廳集合、然后參觀陳云故居;

(2)參觀完后集合、準(zhǔn)備去淀水湖參觀(有3輛車、對應(yīng)3個線程);

說明:必須等大家都到齊了才能去下個地方、比如說在公司集合、3輛車子都到了才能出發(fā)等。要求:用java線程并發(fā)庫的CyclicBarrier類模擬上述參觀過程。

package cn.jp.me;

import java.util.concurrent.BrokenBarrierException;import java.util.concurrent.CyclicBarrier;

public class SingleProcedure implements Runnable {

@Override public void run(){

System.out.println(“ ” + Thread.currentThread().getName()+ “arrives DaTingn And Start Waitting”);public SingleProcedure(CyclicBarrier barrier){ } this.barrier = barrier;private CyclicBarrier barrier;try { barrier.await();} catch(InterruptedException | BrokenBarrierException e){ } System.out.println(“ ” + Thread.currentThread().getName()e.printStackTrace();

}

}

+ “arrives ChenYunGuJunAnd Start Waitting”);try { barrier.await();} catch(InterruptedException | BrokenBarrierException e){ } e.printStackTrace();package cn.jp.me.text;

import java.util.concurrent.CyclicBarrier;

import cn.jp.me.SingleProcedure;

public class Text {

busOne.start();busTwo.start();busThree.start();

Thread busOne = new Thread(component);busOne.setName(“BusOne”);Thread busTwo = new Thread(component);busTwo.setName(“BusTwo”);Thread busThree = new Thread(component);busThree.setName(“BusThree”);

@Override public void run(){ } System.out.println(“All are arrived and Start to next place”);public static void main(String[] args){ CyclicBarrier barrier = new CyclicBarrier(3, new Runnable(){ });SingleProcedure component = new SingleProcedure(barrier);

} }

實驗題4 某圖書館邀請一著名作家簽名售書,大家去買書,具體情況如下:

(1)買書的讀者很多必須排隊,作家簽好名的書不多(但是他還會看書的銷售的情況,一般滿了10本(假設(shè))就不會再簽了);

(2)有的書還沒有簽名,這樣排在前面的同學(xué)就可以買到書、排在后面的就必須等有了簽過名的書才能買;

(3)已經(jīng)簽好名的書可以放在ArrayBlockingQueue中,簽好名的書不斷的向這個隊列里放,而買書的讀者不斷的從里面取書,如沒有簽名的書,就必須等,書有10本了,作家就停下來休息。買書的每個讀者都可以看作一個線程、作家簽名也可以看作是一個線程;

(4)排在前面的讀者先買。要求:編寫程序,模擬上述過程。

package cn.jp.me;

public class Author implements Runnable {

public Author(CommonData data){ } this.data = data;private CommonData data;

}

package cn.jp.me;

public class Reader implements Runnable {

@Override public void run(){

for(int i = 0;i < data.getTimes();++i){

try { buyABook();} catch(InterruptedException e){ public Reader(CommonData data){ } this.data = data;private CommonData data;private void SignABook()throws InterruptedException {

} while(data.getNumber()== 10){

} data.setSign(data.getSign()+ 1);;System.out.println(“The Author Sign NO.” + data.getSign()+ “ book”);data.put(“The Author Sign No.” + data.getSign()+ “Book”);System.out.println(“There Are ” + data.getNumber()+ “Books Signed”);while(data.getNumber()== 10){

} System.out.println(“There Are 10 Books.The Author Chould Rest A While”);Thread.sleep(4000);System.out.println(“There Are 10 Books.The Author Chould Rest A While”);Thread.sleep(4000);} @Override public void run(){

for(int i = 0;i < data.getTimes();++i){

} try {

} SignABook();e.printStackTrace();} catch(InterruptedException e){

}

}

} } e.printStackTrace();private void buyABook()throws InterruptedException {

} while(data.getNumber()== 0){

} data.setBuy(data.getBuy()+ 1);System.out.println(“Buy The No.” + data.getBuy()+ “ Book”);System.out.println(data.getFirBook()+ “Be Bought”);System.out.println(“There Are ” + data.getNumber()+ “Books Signed”);while(data.getNumber()== 0){

} System.out.println(“There Does Not Exist Books Signed.Must Wait……”);Thread.sleep(3000);System.out.println(“There Does Not Exist Books Signed.Must Wait……”);Thread.sleep(3000);package cn.jp.me;

import java.util.concurrent.ArrayBlockingQueue;

public class CommonData {

public String getFirBook()throws InterruptedException { } return queue.take();public int getNumber(){ } return queue.size();public CommonData(int times){

} queue = new ArrayBlockingQueue(10);this.times = times;buy = 0;sign = 0;private ArrayBlockingQueue queue;private int buy, sign;private int times;

} public void put(String elem)throws InterruptedException { } public int getTimes(){ } public int getBuy(){ } public void setBuy(int buy){ } public int getSign(){ } public void setSign(int sign){ } this.sign = sign;return sign;this.buy = buy;return buy;return times;queue.put(elem);package cn.jp.me;

public class Text {

} public static void main(String[] args){

} CommonData data = new CommonData(100);Author author = new Author(data);Reader reader = new Reader(data);new Thread(author).start();new Thread(reader).start();

實驗題5模擬擁有一定數(shù)量賬戶的銀行,把隨機(jī)產(chǎn)生的錢在不同賬號之間進(jìn)行轉(zhuǎn)移交易。每個賬號都有一個線程,在每筆交易中,都會從線程所服務(wù)的賬戶中隨機(jī)取出一定數(shù)額的錢轉(zhuǎn)移到另一個隨機(jī)賬戶中。

提示: 設(shè)計一個Bank類,它有一個transfer方法,該方法將一定數(shù)額的錢從一個賬戶轉(zhuǎn)移到另一個賬戶,如源賬戶沒有足夠余額,該方法直接返回。

package cn.jp.me;

import java.text.Normalizer.Form;

public class Bank {

}

package cn.jp.me;public int getTotalAccountNum(){ } return totalAccountNum;public void setBalance(int accountNo, int num){ } balance[accountNo] = num;public synchronized void transfer(int from, int to, int amount){

} System.out.println(“The Change From ” + from + “ To ” + to);if(balance[from] >= amount){

} System.out.println();System.out.println(“Before Transfer The Balance Of ” + from + “ : ” + balance[from] + “;Of ” + to + “ : ” + balance[to]);System.out.println(“The Change Amount : ” + amount);balance[from]-= amount;balance[to] += amount;System.out.println(“After Transfer The Balance Of ” + from + “ : ” + balance[from] + “;Of ” + to + “ : ” + balance[to]);public Bank(int accountNum){

} totalAccountNum = accountNum;balance = new int[accountNum + 1];private int totalAccountNum;private int[] balance;} else { System.out.println(“The Account ” + from + “'s Balance Is Not Enough”);

import java.util.Random;

import javax.security.auth.login.AccountException;

public class Account implements Runnable {

} package cn.jp.me;

import java.util.Random;import java.util.Scanner;

public class Text {

} Bank bank = new Bank(accountNum);for(int i = 1;i <= accountNum;++i){

} new Thread(new Account(i, random.nextInt(1000000)+ 0, bank)).start();

System.out.println(“Please Input The Number Of Account You Want To Imitate :”);accountNum = scanner.nextInt();public static void main(String[] args){

Random random = new Random();int accountNum;Scanner scanner = new Scanner(System.in);} bank.transfer(accountNo, to, changeNum);@Override public synchronized void run(){ to = random.nextInt(bank.getTotalAccountNum()+ 1);changeNum = random.nextInt(1000000)+ 0;public Account(int accountNo, int initialValue, Bank bank){

} this.accountNo = accountNo;this.bank = bank;bank.setBalance(accountNo, initialValue);private int accountNo;private Bank bank;private static Random random = new Random();int to, changeNum;}

第二篇:Java線程總結(jié)

Java線程總結(jié)

首先要理解線程首先需要了解一些基本的東西,我們現(xiàn)在所使用的大多數(shù)操作系統(tǒng)都屬于多任務(wù),分時操作系統(tǒng)。正是由于這種操作系統(tǒng)的出現(xiàn)才有了多線程這個概念。我們使用的windows,linux就屬于此列。什么是分時操作系統(tǒng)呢,通俗一點與就是可以同一時間執(zhí)行多個程序的操作系統(tǒng),在自己的電腦上面,你是不是一邊聽歌,一邊聊天還一邊看網(wǎng)頁呢?但實際上,并不上cpu在同時執(zhí)行這些程序,cpu只是將時間切割為時間片,然后將時間片分配給這些程序,獲得時間片的程序開始執(zhí)行,不等執(zhí)行完畢,下個程序又獲得時間片開始執(zhí)行,這樣多個程序輪流執(zhí)行一段時間,由于現(xiàn)在cpu的高速計算能力,給人的感覺就像是多個程序在同時執(zhí)行一樣。

一般可以在同一時間內(nèi)執(zhí)行多個程序的操作系統(tǒng)都有進(jìn)程的概念.一個進(jìn)程就是一個執(zhí)行中的程序,而每一個進(jìn)程都有自己獨立的一塊內(nèi)存空間,一組系統(tǒng)資源.在進(jìn)程概念中,每一個進(jìn)程的內(nèi)部數(shù)據(jù)和狀態(tài)都是完全獨立的.因此可以想像創(chuàng)建并執(zhí)行一個進(jìn)程的系統(tǒng)開像是比較大的,所以線程出現(xiàn)了。在java中,程序通過流控制來執(zhí)行程序流,程序中單個順序的流控制稱為線程,多線程則指的是在單個程序中可以同時運行多個不同的線程,執(zhí)行不同的任務(wù).多線程意味著一個程序的多行語句可以看上去幾乎在同一時間內(nèi)同時運行.(你可以將前面一句話的程序換成進(jìn)程,進(jìn)程是程序的一次執(zhí)行過程,是系統(tǒng)運行程序的基本單位)

線程與進(jìn)程相似,是一段完成某個特定功能的代碼,是程序中單個順序的流控制;但與進(jìn)程不同的是,同類的多個線程是共享一塊內(nèi)存空間和一組系統(tǒng)資源,而線程本身的數(shù)據(jù)通常只有微處理器的寄存器數(shù)據(jù),以及一個供程序執(zhí)行時使用的堆棧.所以系統(tǒng)在產(chǎn)生一個線程,或者在各個線程之間切換時,負(fù)擔(dān)要比進(jìn)程小的多,正因如此,線程也被稱為輕負(fù)荷進(jìn)程(light-weight process).一個進(jìn)程中可以包含多個線程.多任務(wù)是指在一個系統(tǒng)中可以同時運行多個程序,即有多個獨立運行的任務(wù),每個任務(wù)對應(yīng)一個進(jìn)程,同進(jìn)程一樣,一個線程也有從創(chuàng)建,運行到消亡的過程,稱為線程的生命周期.用線程的狀態(tài)(state)表明線程處在生命周期的哪個階段.線程有創(chuàng)建,可運行,運行中,阻塞,死亡五中狀態(tài).通過線程的控制與調(diào)度可使線程在這幾種狀態(tài)間轉(zhuǎn)化每個程序至少自動擁有一個線程,稱為主線程.當(dāng)程序加載到內(nèi)存時,啟動主線程.[線程的運行機(jī)制以及調(diào)度模型]

java中多線程就是一個類或一個程序執(zhí)行或管理多個線程執(zhí)行任務(wù)的能力,每個線程可以獨立于其他線程而獨立運行,當(dāng)然也可以和其他線程協(xié)同運行,一個類控制著它的所有線程,可以決定哪個線程得到優(yōu)先級,哪個線程可以訪問其他類的資源,哪個線程開始執(zhí)行,哪個保持休眠狀態(tài)。下面是線程的機(jī)制圖:

Page 1 of 16

線程的狀態(tài)表示線程正在進(jìn)行的活動以及在此時間段內(nèi)所能完成的任務(wù).線程有創(chuàng)建,可運行,運行中,阻塞,死亡五中狀態(tài).一個具有生命的線程,總是處于這五種狀態(tài)之一: 1.創(chuàng)建狀態(tài)

使用new運算符創(chuàng)建一個線程后,該線程僅僅是一個空對象,系統(tǒng)沒有分配資源,稱該線程處于創(chuàng)建狀態(tài)(new thread)2.可運行狀態(tài)

使用start()方法啟動一個線程后,系統(tǒng)為該線程分配了除CPU外的所需資源,使該線程處于可運行狀態(tài)(Runnable)3.運行中狀態(tài)

Java運行系統(tǒng)通過調(diào)度選中一個Runnable的線程,使其占有CPU并轉(zhuǎn)為運行中狀態(tài)(Running).此時,系統(tǒng)真正執(zhí)行線程的run()方法.4.阻塞狀態(tài)

一個正在運行的線程因某種原因不能繼續(xù)運行時,進(jìn)入阻塞狀態(tài)(Blocked)5.死亡狀態(tài)

線程結(jié)束后是死亡狀態(tài)(Dead)

同一時刻如果有多個線程處于可運行狀態(tài),則他們需要排隊等待CPU資源.此時每個線程自動獲得一個線程的優(yōu)先級(priority),優(yōu)先級的高低反映線程的重要或緊急程度.可運行狀態(tài)的線程按優(yōu)先級排隊,線程調(diào)度依據(jù)優(yōu)先級基礎(chǔ)上的“先到先服務(wù)”原則.線程調(diào)度管理器負(fù)責(zé)線程排隊和CPU在線程間的分配,并由線程調(diào)度算法進(jìn)行調(diào)度.當(dāng)線程調(diào)度管理器選種某個線程時,該線程獲得CPU資源而進(jìn)入運行狀態(tài).線程調(diào)度是先占式調(diào)度,即如果在當(dāng)前線程執(zhí)行過程中一個更高優(yōu)先級的線程進(jìn)入可運行狀態(tài),則這個線程立即被調(diào)度執(zhí)行.先占式調(diào)度分為:獨占式和分時方式.獨占方式下,當(dāng)前執(zhí)行線程將一直執(zhí)行下去,直 到執(zhí)行完畢或由于某種原因主動放棄CPU,或CPU被一個更高優(yōu)先級的線程搶占

分時方式下,當(dāng)前運行線程獲得一個時間片,時間到時,即使沒有執(zhí)行完也要讓出

Page 2 of 16

CPU,進(jìn)入可運行狀態(tài),等待下一個時間片的調(diào)度.系統(tǒng)選中其他可運行狀態(tài)的線程執(zhí)行

分時方式的系統(tǒng)使每個線程工作若干步,實現(xiàn)多線程同時運行

另外請注意下面的線程調(diào)度規(guī)則(如果有不理解,不急,往下看): ①如果兩個或是兩個以上的線程都修改一個對象,那么把執(zhí)行修改的方法定義為被同步的(Synchronized),如果對象更新影響到只讀方法,那么只度方法也應(yīng)該定義為同步的

②如果一個線程必須等待一個對象狀態(tài)發(fā)生變化,那么它應(yīng)該在對象內(nèi)部等待,而不是在外部等待,它可以調(diào)用一個被同步的方法,并讓這個方法調(diào)用wait()③每當(dāng)一個方法改變某個對象的狀態(tài)的時候,它應(yīng)該調(diào)用notifyAll()方法,這給等待隊列的線程提供機(jī)會來看一看執(zhí)行環(huán)境是否已發(fā)生改變

④記住wait(),notify(),notifyAll()方法屬于Object類,而不是Thread類,仔細(xì)檢查看是否每次執(zhí)行wait()方法都有相應(yīng)的notify()或notifyAll()方法,且它們作用與相同的對象 在java中每個類都有一個主線程,要執(zhí)行一個程序,那么這個類當(dāng)中一定要有main方法,這個man方法也就是java class中的主線程。你可以自己創(chuàng)建線程,有兩種方法,一是繼承Thread類,或是實現(xiàn)Runnable接口。一般情況下,最好避免繼承,因為java中是單根繼承,如果你選用繼承,那么你的類就失去了彈性,當(dāng)然也不能全然否定繼承Thread,該方法編寫簡單,可以直接操作線程,適用于單重繼承情況。至于選用那一種,具體情況具體分析。

eg.繼承Thread

public class MyThread_1 extends Thread{ public void run(){ //some code } }

eg.實現(xiàn)Runnable接口

public class MyThread_2 implements Runnable { public void run(){ //some code } }

Page 3 of 16

當(dāng)使用繼承創(chuàng)建線程,這樣啟動線程:

new MyThread_1().start()

當(dāng)使用實現(xiàn)接口創(chuàng)建線程,這樣啟動線程:

new Thread(new MyThread_2()).start()

注意,其實是創(chuàng)建一個線程實例,并以實現(xiàn)了Runnable接口的類為參數(shù)傳入這個實例,當(dāng)執(zhí)行這個線程的時候,MyThread_2中run里面的代碼將被執(zhí)行。下面是完成的例子:

public class MyThread implements Runnable { public void run(){ System.out.println(“My Name is ”+Thread.currentThread().getName());} public static void main(String[] args){ new Thread(new MyThread()).start();} }

執(zhí)行后將打印出: My Name is Thread-0

你也可以創(chuàng)建多個線程,像下面這樣

new Thread(new MyThread()).start();new Thread(new MyThread()).start();new Thread(new MyThread()).start();

那么會打印出:

My Name is Thread-0 My Name is Thread-1

Page 4 of 16

My Name is Thread-2

看了上面的結(jié)果,你可能會認(rèn)為線程的執(zhí)行順序是依次執(zhí)行的,但是那只是一般情況,千萬不要用以為是線程的執(zhí)行機(jī)制;影響線程執(zhí)行順序的因素有幾點:首先看看前面提到的優(yōu)先級別

public class MyThread implements Runnable { public void run(){ System.out.println(“My Name is ”+Thread.currentThread().getName());} public static void main(String[] args){ Thread t1=new Thread(new MyThread());Thread t2=new Thread(new MyThread());Thread t3=new Thread(new MyThread());

t2.setPriority(Thread.MAX_PRIORITY);//賦予最高優(yōu)先級

t1.start();t2.start();t3.start();} }

再看看結(jié)果:

My Name is Thread-1 My Name is Thread-0 My Name is Thread-2

Page 5 of 16

線程的優(yōu)先級分為10級,分別用1到10的整數(shù)代表,默認(rèn)情況是5。上面的t2.setPriority(Thread.MAX_PRIORITY)等價與t2.setPriority(10)

然后是線程程序本身的設(shè)計,比如使用sleep,yield,join,wait等方法(詳情請看JDKDocument)

public class MyThread implements Runnable { public void run(){

try {

int sleepTime =(int)(Math.random()* 100);// 產(chǎn)生隨機(jī)數(shù)字,Thread.currentThread().sleep(sleepTime);// 讓其休眠一定時間,時間又上面sleepTime決定

// public static void sleep(long millis)throw InterruptedException

//(API)

System.out.println(Thread.currentThread().getName()+ “ 睡了 ”

+ sleepTime);

} catch(InterruptedException ie)

// 由于線程在休眠可能被中斷,所以調(diào)用sleep方法的時候需要捕捉異常

Page 6 of 16

{

ie.printStackTrace();

} }

public static void main(String[] args){

Thread t1 = new Thread(new MyThread());

Thread t2 = new Thread(new MyThread());

Thread t3 = new Thread(new MyThread());

t1.start();

t2.start();

t3.start();} }

執(zhí)行后觀察其輸出: Thread-0 睡了 11 Thread-2 睡了 48 Thread-1 睡了 69

上面的執(zhí)行結(jié)果是隨機(jī)的,再執(zhí)行很可能出現(xiàn)不同的結(jié)果。由于上面我在run中添加了休眠語句,當(dāng)線程休眠的時候就會讓出cpu,cpu將會選擇執(zhí)行處于runnable狀態(tài)中的其他線程,當(dāng)然也可能出現(xiàn)這種情況,休眠的Thread立即進(jìn)入了runnable狀態(tài),cpu再次執(zhí)行它。[線程組概念] 線程是可以被組織的,java中存在線程組的概念,每個線程都是一個線程組的成員,線程組把多個線程集成為一個對象,通過線程組可以同時對其中的多個線程進(jìn)行操作,如啟動一個線程組的所有線程等.Java的線程組由java.lang包中的Thread——Group類實現(xiàn).ThreadGroup類用來管理一組線程,包括:線程的數(shù)目,線程間的關(guān)系,線程正在執(zhí)行的操作,以及線程將要啟動或終止時間等.線程組還可以包含線程組.在Java的應(yīng)用程序中,最高層的線程組是名位main的線程組,在main中還可以加入線程或

Page 7 of 16

線程組,在mian的子線程組中也可以加入線程和線程組,形成線程組和線程之間的樹狀繼承關(guān)系。像上面創(chuàng)建的線程都是屬于main這個線程組的。借用上面的例子,main里面可以這樣寫:

public static void main(String[] args){

/***************************************

* ThreadGroup(String name)ThreadGroup(ThreadGroup parent, String name)

***********************************/

ThreadGroup group1 = new ThreadGroup(“group1”);

ThreadGroup group2 = new ThreadGroup(group1, “group2”);

Thread t1 = new Thread(group2, new MyThread());

Thread t2 = new Thread(group2, new MyThread());

Thread t3 = new Thread(group2, new MyThread());

t1.start();

t2.start();

t3.start();} 線程組的嵌套,t1,t2,t3被加入group2,group2加入group1。

Page 8 of 16

另外一個比較多就是關(guān)于線程同步方面的,試想這樣一種情況,你有一筆存款在銀行,你在一家銀行為你的賬戶存款,而你的妻子在另一家銀行從這個賬戶提款,現(xiàn)在你有1000塊在你的賬戶里面。你存入了1000,但是由于另一方也在對這筆存款進(jìn)行操作,人家開始執(zhí)行的時候只看到賬戶里面原來的1000元,當(dāng)你的妻子提款1000元后,你妻子所在的銀行就認(rèn)為你的賬戶里面沒有錢了,而你所在的銀行卻認(rèn)為你還有2000元。看看下面的例子:

class BlankSaving // 儲蓄賬戶 { private static int money = 10000;

public void add(int i){

money = money + i;

System.out.println(“Husband 向銀行存入了 [¥” + i + “]”);}

public void get(int i){

money = money-i;

System.out.println(“Wife 向銀行取走了 [¥” + i + “]”);

if(money < 0)

System.out.println(“余額不足!”);}

Page 9 of 16

public int showMoney(){

return money;} }

class Operater implements Runnable { String name;BlankSaving bs;

public Operater(BlankSaving b, String s){

name = s;

bs = b;

}

public static void oper(String name, BlankSaving bs){

if(name.equals(“husband”)){

try {

for(int i = 0;i < 10;i++){

Page 10 of 16

Thread.currentThread().sleep((int)(Math.random()* 300));

bs.add(1000);

}

} catch(InterruptedException e){

}

} else {

try {

for(int i = 0;i < 10;i++){

Thread.currentThread().sleep((int)(Math.random()* 300));

bs.get(1000);

}

} catch(InterruptedException e){

}

} }

public void run(){

oper(name, bs);}

Page 11 of 16

}

public class BankTest { public static void main(String[] args)throws InterruptedException {

BlankSaving bs = new BlankSaving();

Operater o1 = new Operater(bs, “husband”);

Operater o2 = new Operater(bs, “wife”);

Thread t1 = new Thread(o1);

Thread t2 = new Thread(o2);

t1.start();

t2.start();

Thread.currentThread().sleep(500);} }

下面是其中一次的執(zhí)行結(jié)果:

---------first--------------Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000]

Page 12 of 16

Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Husband 向銀行存入了 [¥1000]

看到了嗎,這可不是正確的需求,在husband還沒有結(jié)束操作的時候,wife就插了進(jìn)來,這樣很可能導(dǎo)致意外的結(jié)果。解決辦法很簡單,就是將對數(shù)據(jù)進(jìn)行操作方法聲明為synchronized,當(dāng)方法被該關(guān)鍵字聲明后,也就意味著,如果這個數(shù)據(jù)被加鎖,只有一個對象得到這個數(shù)據(jù)的鎖的時候該對象才能對這個數(shù)據(jù)進(jìn)行操作。也就是當(dāng)你存款的時候,這筆賬戶在其他地方是不能進(jìn)行操作的,只有你存款完畢,銀行管理人員將賬戶解鎖,其他人才能對這個賬戶進(jìn)行操作。

修改public static void oper(String name,BlankSaving bs)為public static void oper(String name,BlankSaving bs),再看看結(jié)果:

Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Husband 向銀行存入了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000] Wife 向銀行取走了 [¥1000]

當(dāng)丈夫完成操作后,妻子才開始執(zhí)行操作,這樣的話,對共享對象的操作就不會有問題了。

[wait and notify] 你可以利用這兩個方法很好的控制線程的執(zhí)行流程,當(dāng)線程調(diào)用wait方法后,線

Page 13 of 16

程將被掛起,直到被另一線程喚醒(notify)或則是如果wait方法指定有時間得話,在沒有被喚醒的情況下,指定時間時間過后也將自動被喚醒。但是要注意一定,被喚醒并不是指馬上執(zhí)行,而是從組塞狀態(tài)變?yōu)榭蛇\行狀態(tài),其是否運行還要看cpu的調(diào)度。事例代碼:

class MyThread_1 extends Thread {

Object lock;

public MyThread_1(Object o){

lock = o;}

public void run(){

try {

synchronized(lock){

System.out.println(“Enter Thread_1 and wait”);

lock.wait();

System.out.println(“be notified”);

}

} catch(InterruptedException e){

} }

Page 14 of 16

}

class MyThread_2 extends Thread { Object lock;

public MyThread_2(Object o){

lock = o;}

public void run(){

synchronized(lock){

System.out.println(“Enter Thread_2 and notify”);

lock.notify();

} } }

public class MyThread { public static void main(String[] args){

int[] in = new int[0];// notice

MyThread_1 t1 = new MyThread_1(in);

Page 15 of 16

MyThread_2 t2 = new MyThread_2(in);

t1.start();

t2.start();} }

執(zhí)行結(jié)果如下:

Enter Thread_1 and wait Enter Thread_2 and notify Thread_1 be notified

可能你注意到了在使用wait and notify方法得時候我使用了synchronized塊來包裝這兩個方法,這是由于調(diào)用這兩個方法的時候線程必須獲得鎖,也就是上面代碼中的lock[],如果你不用synchronized包裝這兩個方法的得話,又或則鎖不一是同一把,比如在MyThread_2中synchronized(lock)改為synchronized(this),那么執(zhí)行這個程序的時候?qū)伋鰆ava.lang.IllegalMonitorStateException執(zhí)行期異常。另外wait and notify方法是Object中的,并不在Thread這個類中。最后你可能注意到了這點:int[] in=new int[0];為什么不是創(chuàng)建new Object而是一個0長度的數(shù)組,那是因為在java中創(chuàng)建一個0長度的數(shù)組來充當(dāng)鎖更加高效。

Page 16 of 16

第三篇:Java線程編程總結(jié)

線程編程方面

60、java中有幾種方法可以實現(xiàn)一個線程?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?

答:有兩種實現(xiàn)方法,分別是繼承Thread類與實現(xiàn)Runnable接口 用synchronized關(guān)鍵字修飾同步方法

反對使用stop(),是因為它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處于一種不連貫狀態(tài),那么其他線程能在那種狀態(tài)下檢查和修改它們。結(jié)果很難檢查出真正的問題所在。suspend()方法容易發(fā)生死鎖。調(diào)用suspend()的時候,目標(biāo)線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被“掛起”的線程恢復(fù)運行。對任何線程來說,如果它們想恢復(fù)目標(biāo)線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應(yīng)該使用suspend(),而應(yīng)在自己的Thread類中置入一個標(biāo)志,指出線程應(yīng)該活動還是掛起。若標(biāo)志指出線程應(yīng)該掛起,便用wait()命其進(jìn)入等待狀態(tài)。若標(biāo)志指出線程應(yīng)當(dāng)恢復(fù),則用一個notify()重新啟動線程。61、sleep()和 wait()有什么區(qū)別? 答:sleep是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時間,給執(zhí)行機(jī)會給其他線程,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復(fù)。調(diào)用sleep不會釋放對象鎖。

wait是Object類的方法,對此對象調(diào)用wait方法導(dǎo)致本線程放棄對象鎖,進(jìn)入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對象鎖定池準(zhǔn)備獲得對象鎖進(jìn)入運行狀態(tài)。

62、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。

答:如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進(jìn)行同步存取。

當(dāng)應(yīng)用程序在對象上調(diào)用了一個需要花費很長時間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時,就應(yīng)該使用異步編程,在很多情況下采用異步途徑往往更有效率。63、啟動一個線程是用run()還是start()? 答:啟動一個線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會立即運行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個線程。

64、當(dāng)一個線程進(jìn)入一個對象的一個synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法? 答:不能,一個對象的一個synchronized方法只能由一個線程訪問。

我認(rèn)為:其他線程可以進(jìn)入非synchronized方法,但不能進(jìn)入這個對象的synchronized方法。65、請說出你所知道的線程同步的方法。

答:wait():使一個線程處于等待狀態(tài),并且釋放所持有的對象的lock。

sleep():使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException異常。

notify():喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由JVM確定喚醒哪個線程,而且不是按優(yōu)先級。

Allnotity():喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。

66、多線程有幾種實現(xiàn)方法,都是什么?同步有幾種實現(xiàn)方法,都是什么? 答:多線程有兩種實現(xiàn)方法,分別是繼承Thread類與實現(xiàn)Runnable接口 同步的實現(xiàn)方面有兩種,分別是synchronized,wait與notify 67、線程的基本概念、線程的基本狀態(tài)以及狀態(tài)之間的關(guān)系

答:線程指在程序執(zhí)行過程中,能夠執(zhí)行程序代碼的一個執(zhí)行單位,每個程序至少都有一個線程,也就是程序本身。

Java中的線程有四種狀態(tài)分別是:運行、就緒、掛起、結(jié)束

68、簡述synchronized和java.util.concurrent.locks.Lock的異同 ? 答:主要相同點:Lock能完成synchronized所實現(xiàn)的所有功能

主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。

Jsp方面

69、forward 和redirect的區(qū)別

答:forward是服務(wù)器請求資源,服務(wù)器直接訪問目標(biāo)地址的URL,把那個URL的響應(yīng)內(nèi)容讀取過來,然后把這些內(nèi)容再發(fā)給瀏覽器,瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容是從哪兒來的,所以它的地址欄中還是原來的地址。

redirect就是服務(wù)端根據(jù)邏輯,發(fā)送一個狀態(tài)碼,告訴瀏覽器重新去請求那個地址,一般來說瀏覽器會用剛才請求的所有參數(shù)重新請求,所以session,request參數(shù)都可以獲取。70、jsp有哪些內(nèi)置對象?作用分別是什么?

答:JSP共有以下9種基本內(nèi)置組件(可與ASP的6種內(nèi)部組件相對應(yīng)):

request 用戶端請求,此請求會包含來自GET/POST請求的參數(shù)

response 網(wǎng)頁傳回用戶端的回應(yīng)

pageContext 網(wǎng)頁的屬性是在這里管理

session 與請求有關(guān)的會話期

application servlet 正在執(zhí)行的內(nèi)容

out 用來傳送回應(yīng)的輸出 config servlet的構(gòu)架部件

page JSP網(wǎng)頁本身

exception 針對錯誤網(wǎng)頁,未捕捉的例外

71、jsp有哪些動作?作用分別是什么? 答:JSP共有以下6種基本動作

jsp:include:在頁面被請求的時候引入一個文件。

jsp:useBean:尋找或者實例化一個JavaBean。

jsp:setProperty:設(shè)置JavaBean的屬性。

jsp:getProperty:輸出某個JavaBean的屬性。

jsp:forward:把請求轉(zhuǎn)到一個新的頁面。

jsp:plugin:根據(jù)瀏覽器類型為Java插件生成OBJECT或EMBED標(biāo)記 72、JSP中動態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別?

答:動態(tài)INCLUDE用jsp:include動作實現(xiàn)

它總是會檢查所含文件中的變化,適合用于包含動態(tài)頁面,并且可以帶參數(shù)

靜態(tài)INCLUDE用include偽碼實現(xiàn),定不會檢查所含文件的變化,適用于包含靜態(tài)頁面

<%@ include file=“included.htm” %> 73、兩種跳轉(zhuǎn)方式分別是什么?有什么區(qū)別? 答:有兩種,分別為:

前者頁面不會轉(zhuǎn)向include所指的頁面,只是顯示該頁的結(jié)果,主頁面還是原來的頁面。執(zhí)行完后還會回來,相當(dāng)于函數(shù)調(diào)用。并且可以帶參數(shù).后者完全轉(zhuǎn)向新頁面,不會再回來。相當(dāng)于go to 語句。

74、JSP的內(nèi)置對象及方法。

答:request表示HttpServletRequest對象。它包含了有關(guān)瀏覽器請求的信息,并且提供了幾個用于獲取cookie, header, 和session數(shù)據(jù)的有用的方法。

response表示HttpServletResponse對象,并提供了幾個用于設(shè)置送回 瀏覽器的響應(yīng)的方法(如cookies,頭信息等)

out對象是javax.jsp.JspWriter的一個實例,并提供了幾個方法使你能用于向瀏覽器回送輸出結(jié)果。

pageContext表示一個javax.servlet.jsp.PageContext對象。它是用于方便存取各種范圍的名字空間、servlet相關(guān)的對象的API,并且包裝了通用的servlet相關(guān)功能的方法。

session表示一個請求的javax.servlet.http.HttpSession對象。Session可以存貯用戶的狀態(tài)信息

applicaton 表示一個javax.servle.ServletContext對象。這有助于查找有關(guān)servlet引擎和servlet環(huán)境的信息

config表示一個javax.servlet.ServletConfig對象。該對象用于存取servlet實例的初始化參數(shù)。page表示從該頁面產(chǎn)生的一個servlet實例

Servlet方面

75、說一說Servlet的生命周期?

答:servlet有良好的生存期的定義,包括加載和實例化、初始化、處理請求以及服務(wù)結(jié)束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達(dá)。Servlet被服務(wù)器實例化后,容器運行其init方法,請求到達(dá)時運行其service方法,service方法自動派遣運行與請求對應(yīng)的doXXX方法(doGet,doPost)等,當(dāng)服務(wù)器決定將實例銷毀的時候調(diào)用其destroy方法。

與cgi的區(qū)別在于servlet處于服務(wù)器進(jìn)程中,它通過多線程方式運行其service方法,一個實例可以服務(wù)于多個請求,并且其實例一般不會銷毀,而CGI對每個請求都產(chǎn)生新的進(jìn)程,服務(wù)完成后就銷毀,所以效率上低于servlet。

76、JAVA SERVLET API中forward()與redirect()的區(qū)別?

答:前者僅是容器中控制權(quán)的轉(zhuǎn)向,在客戶端瀏覽器地址欄中不會顯示出轉(zhuǎn)向后的地址;后者則是完全的跳轉(zhuǎn),瀏覽器將會得到跳轉(zhuǎn)的地址,并重新發(fā)送請求鏈接。這樣,從瀏覽器的地址欄中可以看到跳轉(zhuǎn)后的鏈接地址。所以,前者更加高效,在前者可以滿足需要時,盡量使用forward()方法,并且,這樣也有助于隱藏實際的鏈接。在有些情況下,比如,需要跳轉(zhuǎn)到一個其它服務(wù)器上的資源,則必須使用sendRedirect()方法。77、Servlet的基本架構(gòu) 答:

public class ServletName extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { } public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { } }

78、什么情況下調(diào)用doGet()和doPost()?

答:Jsp頁面中的form標(biāo)簽里的method屬性為get時調(diào)用doGet(),為post時調(diào)用doPost()。79、servlet的生命周期

答:web容器加載servlet,生命周期開始。通過調(diào)用servlet的init()方法進(jìn)行servlet的初始化。通過調(diào)用service()方法實現(xiàn),根據(jù)請求的不同調(diào)用不同的do***()方法。結(jié)束服務(wù),web容器調(diào)用servlet的destroy()方法。

80、如何現(xiàn)實servlet的單線程模式 答:<%@ page isThreadSafe=“false”%> 81、頁面間對象傳遞的方法

答:request,session,application,cookie等

82、JSP和Servlet有哪些相同點和不同點,他們之間的聯(lián)系是什么?

答:JSP是Servlet技術(shù)的擴(kuò)展,本質(zhì)上是Servlet的簡易方式,更強(qiáng)調(diào)應(yīng)用的外表表達(dá)。JSP編譯后是“類servlet”。Servlet和JSP最主要的不同點在于,Servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來。而JSP的情況是Java和HTML可以組合成一個擴(kuò)展名為.jsp的文件。JSP側(cè)重于視圖,Servlet主要用于控制邏輯。83、四種會話跟蹤技術(shù)

答:會話作用域ServletsJSP 頁面描述

page否是代表與一個頁面相關(guān)的對象和屬性。一個頁面由一個編譯好的 Java servlet 類(可以帶有任何的 include 指令,但是沒有 include 動作)表示。這既包括 servlet 又包括被編譯成 servlet 的 JSP 頁面

request是是代表與 Web 客戶機(jī)發(fā)出的一個請求相關(guān)的對象和屬性。一個請求可能跨越多個頁面,涉及多個 Web 組件(由于 forward 指令和 include 動作的關(guān)系)

session是是代表與用于某個 Web 客戶機(jī)的一個用戶體驗相關(guān)的對象和屬性。一個 Web 會話可以也經(jīng)常會跨越多個客戶機(jī)請求

application是是代表與整個 Web 應(yīng)用程序相關(guān)的對象和屬性。這實質(zhì)上是跨越整個 Web 應(yīng)用程序,包括多個頁面、請求和會話的一個全局作用域 84、Request對象的主要方法 答:

setAttribute(String name,Object):設(shè)置名字為name的request的參數(shù)值 getAttribute(String name):返回由name指定的屬性值

getAttributeNames():返回request對象所有屬性的名字集合,結(jié)果是一個枚舉的實例 getCookies():返回客戶端的所有Cookie對象,結(jié)果是一個Cookie數(shù)組 getCharacterEncoding():返回請求中的字符編碼方式 getContentLength():返回請求的Body的長度

getHeader(String name):獲得HTTP協(xié)議定義的文件頭信息 getHeaders(String name):返回指定名字的request Header的所有值,結(jié)果是一個枚舉的實例 getHeaderNames():返回所以request Header的名字,結(jié)果是一個枚舉的實例 getInputStream():返回請求的輸入流,用于獲得請求中的數(shù)據(jù) getMethod():獲得客戶端向服務(wù)器端傳送數(shù)據(jù)的方法

getParameter(String name):獲得客戶端傳送給服務(wù)器端的有name指定的參數(shù)值

getParameterNames():獲得客戶端傳送給服務(wù)器端的所有參數(shù)的名字,結(jié)果是一個枚舉的實例 getParameterValues(String name):獲得有name指定的參數(shù)的所有值 getProtocol():獲取客戶端向服務(wù)器端傳送數(shù)據(jù)所依據(jù)的協(xié)議名稱 getQueryString():獲得查詢字符串

getRequestURI():獲取發(fā)出請求字符串的客戶端地址 getRemoteAddr():獲取客戶端的IP地址 getRemoteHost():獲取客戶端的名字

getSession([Boolean create]):返回和請求相關(guān)Session getServerName():獲取服務(wù)器的名字

getServletPath():獲取客戶端所請求的腳本文件的路徑 getServerPort():獲取服務(wù)器的端口號

removeAttribute(String name):刪除請求中的一個屬性

85、我們在web應(yīng)用開發(fā)過程中經(jīng)常遇到輸出某種編碼的字符,如iso8859-1等,如何輸出一個某種編碼的字符串? 答:

Public String translate(String str){ String tempStr = “";try { tempStr = new String(str.getBytes(”ISO-8859-1“), ”GBK");tempStr = tempStr.trim();} catch(Exception e){ System.err.println(e.getMessage());} return tempStr;} 86、Servlet執(zhí)行時一般實現(xiàn)哪幾個方法? 答:

public void init(ServletConfig config)public ServletConfig getServletConfig()public String getServletInfo()public void service(ServletRequest request,ServletResponse response)public void destroy()

Jdbc、Jdo方面88、Jdo是什么?

87、Class.forName的作用?為什么要用?

答:調(diào)用該訪問返回一個以字符串指定類名的類的對象。答:JDO是Java對象持久化的新的規(guī)范,為java data object的簡稱,也是一個用于存取某種數(shù)據(jù)倉庫中的對象的標(biāo)準(zhǔn)化API。JDO提供了透明的對象存儲,因此對開發(fā)人員來說,存儲數(shù)據(jù)對象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開發(fā)人員解脫出來,從而集中時間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因為它可以在任何數(shù)據(jù)底層上運行。JDBC只是面向關(guān)系數(shù)據(jù)庫(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲功能,比如關(guān)系數(shù)據(jù)庫、文件、XML以及對象數(shù)據(jù)庫(ODBMS)等等,使得應(yīng)用可移植性更強(qiáng)。89、說出數(shù)據(jù)連接池的工作機(jī)制是什么? 答:J2EE服務(wù)器啟動時會建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接。客戶端程序需要連接時,池驅(qū)動程序會返回一個未使用的池連接并將其表記為忙。如果當(dāng)前沒有空閑連接,池驅(qū)動程序就新建一定數(shù)量的連接,新建連接的數(shù)量有配置參數(shù)決定。當(dāng)使用的池連接調(diào)用完成后,池驅(qū)動程序?qū)⒋诉B接表記為空閑,其他調(diào)用就可以使用這個連接。90、Jdo是什么? 答:JDO是Java對象持久化的新的規(guī)范,為java data object的簡稱,也是一個用于存取某種數(shù)據(jù)倉庫中的對象的標(biāo)準(zhǔn)化API。JDO提供了透明的對象存儲,因此對開發(fā)人員來說,存儲數(shù)據(jù)對象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開發(fā)人員解脫出來,從而集中時間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因為它可以在任何數(shù)據(jù)底層上運行。JDBC只是面向關(guān)系數(shù)據(jù)庫(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲功能,比如關(guān)系數(shù)據(jù)庫、文件、XML以及對象數(shù)據(jù)庫(ODBMS)等等,使得應(yīng)用可移植性更強(qiáng)。

Xml方面

91、xml有哪些解析技術(shù)?區(qū)別是什么? 答:有DOM,SAX,STAX等

DOM:處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個文檔裝入內(nèi)存,適合對XML的隨機(jī)訪問。

SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當(dāng)遇到像文件開頭,文檔結(jié)束,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時,它會觸發(fā)一個事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問 STAX:Streaming API for XML(StAX)92、你在項目中用到了xml技術(shù)的哪些方面?如何實現(xiàn)的?

答:用到了數(shù)據(jù)存貯,信息配置兩方面。在做數(shù)據(jù)交換平臺時,將不能數(shù)據(jù)源的數(shù)據(jù)組裝成XML文件,然后將XML文件壓縮打包加密后通過網(wǎng)絡(luò)傳送給接收者,接收解密與解壓縮后再同XML文件中還原相關(guān)信息進(jìn)行處理。在做軟件配置時,利用XML可以很方便的進(jìn)行,軟件的各種配置參數(shù)都存貯在XML文件中。

93、XML文檔定義有幾種形式?它們之間有何本質(zhì)區(qū)別?解析XML文檔有哪幾種方式? 答:a: 兩種形式 dtd schema,b: 本質(zhì)區(qū)別:schema本身是xml的,可以被XML解析器解析(這也是從DTD上發(fā)展schema的根本目的),c:有DOM,SAX,STAX等

DOM:處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且DOM必須在解析文件之前把整個文檔裝入內(nèi)存,適合對XML的隨機(jī)訪問

SAX:不現(xiàn)于DOM,SAX是事件驅(qū)動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當(dāng)遇到像文件開頭,文檔結(jié)束,或者標(biāo)簽開頭與標(biāo)簽結(jié)束時,它會觸發(fā)一個事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問 STAX:Streaming API for XML(StAX)

第四篇:Weblogic線程堆棧獲取方式小結(jié)

Weblogic線程堆棧獲取方式小結(jié)

當(dāng)服務(wù)器掛起,崩潰或者性能底下時,就需要抓取服務(wù)器的線程堆棧(Thread Dump)用于后續(xù)的分析.Thread dump提供了當(dāng)前活動的線程的快照.它提供了JVM中所有Java線程的棧跟蹤信息,有很多方式可用于獲取Thread Dump, 一些是操作系統(tǒng)特定的命令.操作系統(tǒng)命令獲取ThreadDump: Windows: 轉(zhuǎn)向服務(wù)器的標(biāo)準(zhǔn)輸出窗口并按下Control + Break組合鍵, 之后需要將線程堆棧復(fù)制到文件中

UNIX/ Linux 首先查找到服務(wù)器的進(jìn)程號(process id), 然后獲取堆棧.1.ps –ef | grep java 2.kill-3

注意一定要謹(jǐn)慎, 一步不慎就可能讓服務(wù)器進(jìn)程被殺死!JVM 自帶的工具獲取線程堆棧: JDK自帶命令行工具獲取PID并做ThreadDump: 1.jps 2.jstack

3.使用JVisualVM: Threads 標(biāo)簽頁àThreadDump按鈕.WebLogic 自帶的獲取 thread dump的工具: 1.webLogic.Admin 工具

a.打開命令提示符, 通過運行/bin/setDomain.env設(shè)置相關(guān)類路徑

b.執(zhí)行下面的命令

java weblogic.Admin-url t3://localhost:7001-username weblogic-password weblogic1 THREAD_DUMP 注意: Thread Dump 會打印到標(biāo)準(zhǔn)輸出, 如nohup日志或者進(jìn)程窗口.2.使用 Admin Console a.登錄 Admin Console , 點擊對應(yīng)的服務(wù)器 b.點擊Server à Monitoring àThreads c.點擊: Dump Thread Stack 按鈕 3.使用WLST(WebLogic Scripting Tool)connect(‘weblogic’,'weblogic1’,’t3://localhost:7001’)cd(‘Servers’)cd(‘AdminServer’)threadDump()disconnect()exit()注意: 線程堆棧將會保存在運行wlst的當(dāng)前目錄下.4.使用utils.ThreadDumper 用法: C:beawlserver_10.3serverlib>java utils.ThreadDumper Broadcast Thread

dumps

disabled:

must

specify

-cp

weblogic.jar weblogic.debug.dumpThreadAddr and weblogic.debug.dumpThreadPort Exception in thread “main” java.lang.IllegalArgumentException: Port out of range :-1 at java.net.DatagramPacket.setPort(Unknown Source)at java.net.DatagramPacket.(Unknown Source)at java.net.DatagramPacket.(Unknown Source)at utils.ThreadDumper.sendDumpMsg(ThreadDumper.java:124)at utils.ThreadDumper.main(ThreadDumper.java:145)5.如果服務(wù)器是作為Windows服務(wù)的方式運行, 請運行下列命令: WL_HOMEbinbeasvc-dump-svcname:service-name 其它一些獲取Thread Dump的工具有jrcmd, jrmc(JRockit VM自帶),Samurai, JProfiler等, 還可通過JMX編程的方式獲取, 如JDK自帶示例代碼: $JAVA_HOMEdemomanagementFullThreadDump

第五篇:Java程序員必須掌握的線程知識

Java程序員必須掌握的線程知識 Callable和Future Callable和Future出現(xiàn)的原因

創(chuàng)建線程的2種方式,一種是直接繼承Thread,另外一種就是實現(xiàn)Runnable接口。

這2種方式都有一個缺陷就是:在執(zhí)行完任務(wù)之后無法獲取執(zhí)行結(jié)果。如果需要獲取執(zhí)行結(jié)果,就必須通過共享變量或者使用線程通信的方式來達(dá)到效果,這樣使用起來就比較麻煩。

而自從Java 1.5開始,就提供了Callable和Future,通過它們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。

Callable和Future介紹

Callable接口代表一段可以調(diào)用并返回結(jié)果的代碼;Future接口表示異步任務(wù),是還沒有完成的任務(wù)給出的未來結(jié)果。所以說Callable用于產(chǎn)生結(jié)果,F(xiàn)uture用于獲取結(jié)果。

Callable接口使用泛型去定義它的返回類型。Executors類提供了一些有用的方法在線程池中執(zhí)行Callable內(nèi)的任務(wù)。由于Callable任務(wù)是并行的(并行就是整體看上去是并行的,其實在某個時間點只有一個線程在執(zhí)行),我們必須等待它返回的結(jié)果。

java.util.concurrent.Future對象為我們解決了這個問題。在線程池提交Callable任務(wù)后返回了一個Future對象,使用它可以知道Callable任務(wù)的狀態(tài)和得到Callable返回的執(zhí)行結(jié)果。Future提供了get()方法讓我們可以等待Callable結(jié)束并獲取它的執(zhí)行結(jié)果。

Callable與Runnable

java.lang.Runnable吧,它是一個接口,在它里面只聲明了一個run()方法:

publicinterfaceRunnable{

publicabstractvoid run();}

由于run()方法返回值為void類型,所以在執(zhí)行完任務(wù)之后無法返回任何結(jié)果。

Callable位于java.util.concurrent包下,它也是一個接口,在它里面也只聲明了一個方法,只不過這個方法叫做call():

publicinterfaceCallable{

/**

* Computes a result, or throws an exception if unable to do so.*

* @return computed result

* @throws Exception if unable to compute a result

*/

V call()throwsException;}

可以看到,這是一個泛型接口,call()函數(shù)返回的類型就是傳遞進(jìn)來的V類型。

那么怎么使用Callable呢?

一般情況下是配合ExecutorService來使用的,在ExecutorService接口中聲明了若干個submit方法的重載版本:

Future submit(Callable task); Future submit(Runnable task, T result);Future submit(Runnable task);

第一個submit方法里面的參數(shù)類型就是Callable。

暫時只需要知道Callable一般是和ExecutorService配合來使用的,具體的使用方法講在后面講述。

一般情況下我們使用第一個submit方法和第三個submit方法,第二個submit方法很少使用。

Future

Future就是對于具體的Runnable或者Callable任務(wù)的執(zhí)行結(jié)果進(jìn)行取消、查詢是否完成、獲取結(jié)果。必要時可以通過get方法獲取執(zhí)行結(jié)果,該方法會阻塞直到任務(wù)返回結(jié)果。

Future類位于java.util.concurrent包下,它是一個接口:

publicinterfaceFuture{

boolean cancel(boolean mayInterruptIfRunning);

boolean isCancelled();

boolean isDone();

V get()throwsInterruptedException,ExecutionException;

V get(long timeout,TimeUnit unit)

throwsInterruptedException,ExecutionException,TimeoutException;}

在Future接口中聲明了5個方法,下面依次解釋每個方法的作用:

cancel方法用來取消任務(wù),如果取消任務(wù)成功則返回true,如果取消任務(wù)失敗則返回false。參數(shù)mayInterruptIfRunning表示是否允許取消正在執(zhí)行卻沒有執(zhí)行完畢的任務(wù),如果設(shè)置true,則表示可以取消正在執(zhí)行過程中的任務(wù)。如果任務(wù)已經(jīng)完成,則無論mayInterruptIfRunning為true還是false,此方法肯定返回false,即如果取消已經(jīng)完成的任務(wù)會返回false;如果任務(wù)正在執(zhí)行,若mayInterruptIfRunning設(shè)置為true,則返回true,若mayInterruptIfRunning設(shè)置為false,則返回false;如果任務(wù)還沒有執(zhí)行,則無論mayInterruptIfRunning為true還是false,肯定返回true。isCancelled方法表示任務(wù)是否被取消成功,如果在任務(wù)正常完成前被取消成功,則返回 true。

isDone方法表示任務(wù)是否已經(jīng)完成,若任務(wù)完成,則返回true;

get()方法用來獲取執(zhí)行結(jié)果,這個方法會產(chǎn)生阻塞,會一直等到任務(wù)執(zhí)行完畢才返回;

get(long timeout, TimeUnit unit)用來獲取執(zhí)行結(jié)果,如果在指定時間內(nèi),還沒獲取到結(jié)果,就直接返回null。

也就是說Future提供了三種功能:

1)判斷任務(wù)是否完成;

2)能夠中斷任務(wù);

3)能夠獲取任務(wù)執(zhí)行結(jié)果。

因為Future只是一個接口,所以是無法直接用來創(chuàng)建對象使用的,因此就有了下面的FutureTask。FutureTask

FutureTask實現(xiàn)了RunnableFuture接口,這個接口的定義如下:

publicinterfaceRunnableFutureextendsRunnable,Future{

void run();}

可以看到這個接口實現(xiàn)了Runnable和Future接口,接口中的具體實現(xiàn)由FutureTask來實現(xiàn)。這個類的兩個構(gòu)造方法如下 :

publicFutureTask(Callable callable){

if(callable ==null)

thrownewNullPointerException();

sync =newSync(callable);

}

publicFutureTask(Runnable runnable, V result){

sync =newSync(Executors.callable(runnable, result));

} 如上提供了兩個構(gòu)造函數(shù),一個以Callable為參數(shù),另外一個以Runnable為參數(shù)。這些類之間的關(guān)聯(lián)對于任務(wù)建模的辦法非常靈活,允許你基于FutureTask的Runnable特性(因為它實現(xiàn)了Runnable接口),把任務(wù)寫成Callable,然后封裝進(jìn)一個由執(zhí)行者調(diào)度并在必要時可以取消的FutureTask。

FutureTask可以由執(zhí)行者調(diào)度,這一點很關(guān)鍵。它對外提供的方法基本上就是Future和Runnable接口的組合:get()、cancel、isDone()、isCancelled()和run(),而run()方法通常都是由執(zhí)行者調(diào)用,我們基本上不需要直接調(diào)用它。

一個FutureTask的例子

publicclassMyCallableimplementsCallable{

privatelong waitTime;

publicMyCallable(int timeInMillis){

this.waitTime=timeInMillis;

}

@Override

publicString call()throwsException{ Thread.sleep(waitTime);

//return the thread name executing this callable task

returnThread.currentThread().getName();

}

}

publicclassFutureTaskExample{

publicstaticvoid main(String[] args){

MyCallable callable1 =newMyCallable(1000);// 要執(zhí)行的任務(wù)

MyCallable callable2 =newMyCallable(2000);

FutureTask futureTask1 =newFutureTask(callable1);// 將Callable寫的任務(wù)封裝到一個由執(zhí)行者調(diào)度的FutureTask對象

FutureTask futureTask2 =newFutureTask(callable2);

ExecutorService executor =Executors.newFixedThreadPool(2);// 創(chuàng)建線程池并返回ExecutorService實例

executor.execute(futureTask1);// 執(zhí)行任務(wù)

executor.execute(futureTask2);

while(true){

try{

if(futureTask1.isDone()&& futureTask2.isDone()){// 兩個任務(wù)都完成System.out.println(“Done”);

executor.shutdown();// 關(guān)閉線程池和服務(wù)

return;

}

if(!futureTask1.isDone()){// 任務(wù)1沒有完成,會等待,直到任務(wù)完成 System.out.println(“FutureTask1 output=”+futureTask1.get());

}

System.out.println(“Waiting for FutureTask2 to complete”);

String s = futureTask2.get(200L,TimeUnit.MILLISECONDS);

if(s!=null){

System.out.println(“FutureTask2 output=”+s);

}

}catch(InterruptedException|ExecutionException e){

e.printStackTrace();

}catch(TimeoutException e){

//do nothing

}

} }}

運行如上程序后,可以看到一段時間內(nèi)沒有輸出,因為get()方法等待任務(wù)執(zhí)行完成然后才輸出內(nèi)容.輸出結(jié)果如下:

FutureTask1 output=pool-1-thread-1WaitingforFutureTask2 to completeWaitingforFutureTask2 to completeWaitingforFutureTask2 to completeWaitingforFutureTask2 to completeWaitingforFutureTask2 to completeFutureTask2 output=pool-1-thread-2Done

下載實驗06 線程應(yīng)用及線程并發(fā)庫word格式文檔
下載實驗06 線程應(yīng)用及線程并發(fā)庫.doc
將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
點此處下載文檔

文檔為doc格式


聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報,并提供相關(guān)證據(jù),工作人員會在5個工作日內(nèi)聯(lián)系你,一經(jīng)查實,本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

相關(guān)范文推薦

    操作系統(tǒng)-創(chuàng)建線程,利用互斥實現(xiàn)線程共享變量通信介紹

    2016-2017學(xué)年度第一學(xué)期大作業(yè) 課程名稱: 操作系統(tǒng)(含課程設(shè)計) 任課教師:解曉萌作業(yè)題目: 創(chuàng)建線程,利用互斥實現(xiàn)線程共享變量通信姓名:魯 斌學(xué)號: 20***02專業(yè): 計算機(jī)科......

    黑馬程序員C語言教程:深入淺出-服務(wù)器高并發(fā)庫libevent5篇范文

    標(biāo)題:深入淺出-服務(wù)器高并發(fā)庫libevent(二) 上一章,我們簡單介紹了libevent的環(huán)境的安裝,和簡單的事例。 現(xiàn)在先不要著急分析他的代碼,在這里我首先要介紹一個專業(yè)名詞“Reactor......

    實驗五 電子商務(wù)及其應(yīng)用

    廣東海洋大學(xué)寸金學(xué)院學(xué)生實驗報告書 實驗名稱 系 學(xué)生姓名 實驗六 電子商務(wù)及其應(yīng)用 課程名稱 財務(wù)會計教育 會計電算化 班級學(xué)號 專業(yè)實驗地點 實驗樓303 實驗日期 一、......

    多媒體技術(shù)及應(yīng)用實驗

    實驗一、利用Photoshop制作個性化名片開發(fā)工具:Photoshop CS5 實驗要求:利用合適的素材,再加上自己的創(chuàng)意設(shè)計,設(shè)計出漂亮的一款富有創(chuàng)意的學(xué)生本人的個性化名片。 實驗報告:(1)打......

    實驗6JavaAWT及Swing應(yīng)用

    實驗6 Java AWT及Swing應(yīng)用 實驗內(nèi)容 (1)按鈕有序排列 (2)密碼驗證問題 (3)名片錄入管理界面設(shè)計 (4)文字字體設(shè)計窗體 1、按鈕有序排列 實驗?zāi)康? (1) 了解 GUI 的概念 ;......

    圖的應(yīng)用 實驗(精選5篇)

    圖的應(yīng)用 實驗日志 實驗題目:圖的建立及輸出 實驗?zāi)康模航D的存儲結(jié)構(gòu)(圖的類型可以是有向圖、無向圖、有向網(wǎng)、無向網(wǎng),學(xué)生可以任選兩種類型),能夠輸入圖的頂點和邊的信息,并存......

    實驗二關(guān)于我國信用卡應(yīng)用

    實驗二:關(guān)于我國信用卡應(yīng)用(2學(xué)時) 1.我國各家新興的商業(yè)銀行也都涉足銀行卡領(lǐng)域,紛紛創(chuàng)建具有自身特色的銀行卡品牌,建立了各自的銀行網(wǎng)絡(luò)系統(tǒng)工程。各家銀行的競爭,豐富了銀行卡......

    農(nóng)業(yè)機(jī)械與應(yīng)用實驗教學(xué)大綱

    實驗教學(xué) 實驗一:農(nóng)用柴油機(jī)的曲柄連桿機(jī)構(gòu)拆裝實驗 掌握內(nèi)燃機(jī)拆裝的基本技術(shù)要求和技術(shù)要領(lǐng),學(xué)會正確選用和使用常用工具。掌握內(nèi)燃機(jī)的曲柄連桿機(jī)構(gòu)、正時齒輪室的拆裝。......

主站蜘蛛池模板: 久久久性色精品国产免费观看| 国产情侣一区二区| 国产在线精品成人一区二区三区| 吃奶摸下的激烈视频| 国内精品久久久久国产盗摄| 欧美黑人巨大videos在线| 亚洲男人的天堂av手机在线观看| 国产精品亚洲五月天高清| 国产97成人亚洲综合在线| 亚洲精品国产摄像头| 国产偷国产偷亚洲清高网站| 日产一区日产2区| 国产一区二区三区四区五区vm| 新婚少妇无套内谢国语播放| 国精品午夜福利视频不卡| 欧美精品亚洲精品日韩专区一乛方| 人妻无码αv中文字幕久久琪琪布| 亚洲国产成人精品无码区在线观看| 国产精品特级毛片一区二区| 亚洲熟妇无码一区二区三区导航| 台湾佬中文娱乐网22| 中国丰满熟妇xxxx性| 日韩精品无码久久一区二区三| 日韩av无码免费播放| 久久999精品国产只有精品| 亚洲av永久无码精品一区二区国产| 狠狠躁夜夜躁人人躁婷婷| 狠狠噜天天噜日日噜无码| 国产成人www免费人成看片| 国产人妻人伦精品婷婷| 国产午夜影视大全免费观看| 国产av人人夜夜澡人人爽| 日本久久精品一区二区三区| 日日av拍夜夜添久久免费| 日本成本人片免费网站| 亚洲日本中文字幕乱码在线电影| 国自产偷精品不卡在线| 亚洲欧美人成视频一区在线| 青春草在线视频观看| 国产成人精品午夜福利a| 伊人大香人妻在线播放|