① java如何實現方法的阻塞
你可以嘗試研究下FutureTask類和Callable介面,他們是一種阻塞線程
舉個例子:
ReceiveThread
rt=new
ReceiveThread();
FutureTask
task=new
FutureTask
(rt);
Thread
t=new
Thread(task);
t.start();
String
s=task.get();//阻塞方法,只有當Callable里的call方法運算結束,才會解除阻塞
class
ReceiveThread
implements
Callable
{
public
String
call()
throws
Exception{
while(....){
........
.......
return
String;
}
}
}
那你就寫個線程不斷監聽result這個值不就行了,當監聽到的是關閉的值就列印
② java中如何編程實現阻塞
自己寫阻塞,就是寫個死循環不斷取參數,當參數條件滿足時就調用相應的方法執行,
具體的執行方法可以交給一個線程來執行
③ 如何解決Java線程同步中的阻塞問題
Java線程同步需要我們不斷的進行相關知識的學習,下面我們就來看看如何才能更好的在學習中掌握相關的知識訊息,來完善我們自身的編寫手段。希望大家有所收獲。 Java線程同步的優先順序代表該線程的重要程度,當有多個線程同時處於可執行狀態並等待獲得 CPU 時間時,線程調度系統根據各個線程的優先順序來決定給誰分配 CPU 時間,優先順序高的線程有更大的機會獲得 CPU 時間,優先順序低的線程也不是沒有機會,只是機會要小一些罷了。 你可以調用 Thread 類的方法 getPriority()和 setPriority()來存取Java線程同步的優先順序,線程的優先順序界於1(MIN_PRIORITY)和10(MAX_PRIORITY)之間,預設是5(NORM_PRIORITY)。 Java線程同步 由於同一進程的多個線程共享同一片存儲空間,在帶來方便的同時,也帶來了訪問沖突這個嚴重的問題。Java語言提供了專門機制以解決這種沖突,有效避免了同一個數據對象被多個線程同時訪問。 由於我們可以通過 private 關鍵字來保證數據對象只能被方法訪問,所以我們只需針對方法提出一套機制,這套機制就是 synchronized 關鍵字,它包括兩種用法:synchronized 方法和 synchronized 塊。 1. synchronized 方法:通過在方法聲明中加入 synchronized關鍵字來聲明 synchronized 方法。如:1. public synchronized void accessVal(int newVal); synchronized 方法控制對類成員變數的訪問:每個類實例對應一把鎖,每個 synchronized 方法都必須獲得調用該方法的類實例的鎖方能執行,否則所屬線程阻塞,方法一旦執行,就獨占該鎖,直到從該方法返回時才將鎖釋放,此後被阻塞的Java線程同步方能獲得該鎖,重新進入可執行狀態。 這種機制確保了同一時刻對於每一個類實例,其所有聲明為 synchronized 的成員函數中至多隻有一個處於可執行狀態(因為至多隻有一個能夠獲得該類實例對應的鎖),從而有效避免了類成員變數的訪問沖突(只要所有可能訪問類成員變數的方法均被聲明為 synchronized)。 在 Java 中,不光是類實例,每一個類也對應一把鎖,這樣我們也可將類的靜態成員函數聲明為 synchronized ,以控制其對類的靜態成員變數的訪問。 synchronized 方法的缺陷:若將一個大的方法聲明為synchronized 將會大大影響效率,典型地,若將線程類的方法 run()聲明為 synchronized ,由於在線程的整個生命期內它一直在運行,因此將導致它對本類任何 synchronized 方法的調用都永遠不會成功。當然我們可以通過將訪問類成員變數的代碼放到專門的方法中,將其聲明為 synchronized ,並在主方法中調用來解決這一問題,但是 Java 為我們提供了更好的解決辦法,那就是 synchronized 塊。 2. synchronized 塊:通過 synchronized關鍵字來聲明synchronized 塊。語法如下:1. synchronized(syncObject)2. {3. //允許訪問控制的代碼4. } synchronized 塊是這樣一個代碼塊,其中的代碼必須獲得對象 syncObject (如前所述,可以是類實例或類)的鎖方能執行,具體機制同前所述。由於可以針對任意代碼塊,且可任意指定上鎖的對象,故靈活性較高。 Java線程同步的阻塞 為了解決對共享存儲區的訪問沖突,Java 引入了同步機制,現在讓我們來考察多個Java線程同步對共享資源的訪問,顯然同步機制已經不夠了,因為在任意時刻所要求的資源不一定已經准備好了被訪問,反過來,同一時刻准備好了的資源也可能不止一個。為了解決這種情況下的訪問控制問題,Java 引入了對阻塞機制的支持。 阻塞指的是暫停一個Java線程同步的執行以等待某個條件發生(如某資源就緒),學過操作系統的同學對它一定已經很熟悉了。Java 提供了大量方法來支持阻塞,下面讓我們逐一分析。
④ java阻塞隊列 線程同步合作
Queue介面與List Set同一級別 都是繼承了Collection介面 LinkedList實現了Queue介面 Queue介面窄化了對LinkedList的方法的訪問許可權(即在方法中的參數類型如果是Queue時 就完全只能訪問Queue介面所定義的方法了 而不能直接訪問 LinkedList的非Queue的方法) 以使得只有恰當的方法才可以使用 BlockingQueue 繼承了Queue介面
隊列是一種數據結構.它有兩個基本操作 在隊列尾部加人一個元素 和從隊列頭部移除一個元素就是說 隊列以一種先進先出的方式管理數據 如果你試圖向一個已經滿了的阻塞隊列中添加一個元素或者是從一個空的阻塞隊列中移除一個元索 將導致線程阻塞.在多線程進行合作時 阻塞隊列是很有用的工具 工作者線程可以定期地把中間結果存到阻塞隊列中而其他工作者線線程把中間結果取出並在將來修改它們 隊列會自動平衡負載 如果第一個線程集運行得比第二個慢 則第二個線程集在等待結果時就會阻塞 如果第一個線程集運行得快 那麼它將等待第二個線程集趕上來 下表顯示了jdk 中的阻塞隊列的操作
add 增加一個元索 如果隊列已春慎橋滿 則拋出一個IIIegaISlabEepeplian異常
remove 移除並返回隊列頭部的元素 如果隊列為空 則拋出一個NoSuchElementException異常
element 返回隊列頭部的元素 如果隊列為空 則拋出一個NoSuchElementException異常
offer 添加一個元素並返回true 如果隊列已滿 則返回false
poll 移除並返問隊列頭部的元素 如果隊列扒猛為空 則返回null
peek 返回隊列頭部的元素 如果隊列為空 則返回null
put 添加一個元素 如果隊列滿 則阻塞
take 移除並返回隊列頭部的元素 如果隊列為空 則阻塞
remove element offer poll peek 其實是屬於Queue介面
阻塞隊列的操作可以根據它們的響應方式分為以下三類 aad removee和element操作在你試圖為一個已滿的隊列增加元素或從空隊列取得元素時拋出異常 當然 在多線程程序中 隊列在任何時間都可能變成滿的或空的 所以你可能想使用offer poll peek方法 這些方法在無法完成任務時只是給出一個出錯示而不會拋出異常
注意 poll和peek方法出錯進返回null 因此 向隊列中插入null值是不合法的
還有帶超時的offer和poll方法變種 例如 下面的調用
boolean success = q offer(x TimeUnit MILLISECONDS);
嘗試在 毫秒內向隊列尾部插入一個元素 如果成功 立即返回true 否則 當到達超時進 返回false 同樣地 調用
Object head = q poll( TimeUnit MILLISECONDS);
如果在 毫秒內成功地移除了隊列頭元素 則立即返回頭元素 否則在到達超時時 返回null
最後 我們有阻塞操作put和take put方法在隊列滿時阻塞 take方法在隊列空時阻塞
ncurrent包提供了阻塞隊列的 個變種 默認情況下 LinkedBlockingQueue的容量是沒有上限的(說的不準確 在不指定時容量為Integer MAX_VALUE 不要然的話在put時怎麼會受阻呢) 但是也可以選擇指定其最大容量 它是基孝仔於鏈表的隊列 此隊列按 FIFO(先進先出)排序元素
ArrayBlockingQueue在構造時需要指定容量 並可以選擇是否需要公平性 如果公平參數被設置true 等待時間最長的線程會優先得到處理(其實就是通過將ReentrantLock設置為true來達到這種公平性的 即等待時間最長的線程會先操作) 通常 公平性會使你在性能上付出代價 只有在的確非常需要的時候再使用它 它是基於數組的阻塞循環隊列 此隊列按 FIFO(先進先出)原則對元素進行排序
PriorityBlockingQueue是一個帶優先順序的隊列 而不是先進先出隊列 元素按優先順序順序被移除 該隊列也沒有上限(看了一下源碼 PriorityBlockingQueue是對PriorityQueue的再次包裝 是基於堆數據結構的 而PriorityQueue是沒有容量限制的 與ArrayList一樣 所以在優先阻塞隊列上put時是不會受阻的 雖然此隊列邏輯上是無界的 但是由於資源被耗盡 所以試圖執行添加操作可能會導致 OutOfMemoryError) 但是如果隊列為空 那麼取元素的操作take就會阻塞 所以它的檢索操作take是受阻的 另外 往入該隊列中的元素要具有比較能力
最後 DelayQueue(基於PriorityQueue來實現的)是一個存放Delayed 元素的無界阻塞隊列 只有在延遲期滿時才能從中提取元素 該隊列的頭部是延遲期滿後保存時間最長的 Delayed 元素 如果延遲都還沒有期滿 則隊列沒有頭部 並且poll將返回null 當一個元素的 getDelay(TimeUnit NANOSECONDS) 方法返回一個小於或等於零的值時 則出現期滿 poll就以移除這個元素了 此隊列不允許使用 null 元素 下面是延遲介面
Java代碼
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
放入DelayQueue的元素還將要實現pareTo方法 DelayQueue使用這個來為元素排序
下面的實例展示了如何使用阻塞隊列來控制線程集 程序在一個目錄及它的所有子目錄下搜索所有文件 列印出包含指定關鍵字的文件列表 從下面實例可以看出 使用阻塞隊列兩個顯著的好處就是 多線程操作共同的隊列時不需要額外的同步 另外就是隊列會自動平衡負載 即那邊(生產與消費兩邊)處理快了就會被阻塞掉 從而減少兩邊的處理速度差距 下面是具體實現
Java代碼
public class BlockingQueueTest {
public static void main(String[] args) {
Scanner in = new Scanner(System in);
System out print( Enter base directory (e g /usr/local/jdk /src): );
String directory = in nextLine();
System out print( Enter keyword (e g volatile): );
String keyword = in nextLine();
final int FILE_QUEUE_SIZE = ;// 阻塞隊列大小
final int SEARCH_THREADS = ;// 關鍵字搜索線程個數
// 基於ArrayBlockingQueue的阻塞隊列
BlockingQueue<File> queue = new ArrayBlockingQueue<File>(
FILE_QUEUE_SIZE);
//只啟動一個線程來搜索目錄
FileEnumerationTask enumerator = new FileEnumerationTask(queue
new File(directory));
new Thread(enumerator) start();
//啟動 個線程用來在文件中搜索指定的關鍵字
for (int i = ; i <= SEARCH_THREADS; i++)
new Thread(new SearchTask(queue keyword)) start();
}
}
class FileEnumerationTask implements Runnable {
//啞元文件對象 放在阻塞隊列最後 用來標示文件已被遍歷完
public static File DUMMY = new File( );
private BlockingQueue<File> queue;
private File startingDirectory;
public FileEnumerationTask(BlockingQueue<File> queue File startingDirectory) {
this queue = queue;
this startingDirectory = startingDirectory;
}
public void run() {
try {
enumerate(startingDirectory);
queue put(DUMMY);//執行到這里說明指定的目錄下文件已被遍歷完
} catch (InterruptedException e) {
}
}
// 將指定目錄下的所有文件以File對象的形式放入阻塞隊列中
public void enumerate(File directory) throws InterruptedException {
File[] files = directory listFiles();
for (File file : files) {
if (file isDirectory())
enumerate(file);
else
//將元素放入隊尾 如果隊列滿 則阻塞
queue put(file);
}
}
}
class SearchTask implements Runnable {
private BlockingQueue<File> queue;
private String keyword;
public SearchTask(BlockingQueue<File> queue String keyword) {
this queue = queue;
this keyword = keyword;
}
public void run() {
try {
boolean done = false;
while (!done) {
//取出隊首元素 如果隊列為空 則阻塞
File file = queue take();
if (file == FileEnumerationTask DUMMY) {
//取出來後重新放入 好讓其他線程讀到它時也很快的結束
queue put(file);
done = true;
} else
search(file);
}
} catch (IOException e) {
e printStackTrace();
} catch (InterruptedException e) {
}
}
public void search(File file) throws IOException {
Scanner in = new Scanner(new FileInputStream(file));
int lineNumber = ;
while (in hasNextLine()) {
lineNumber++;
String line = in nextLine();
if (ntains(keyword))
System out printf( %s:%d:%s%n file getPath() lineNumber
line);
}
in close();
}
lishixin/Article/program/Java/hx/201311/26657
⑤ java調優設置阻塞隊列大小
阻塞隊列大小的調整是Java調優的改鄭一個重要環節,它可以幫助減少內存的使用,提升程序的運行效率。Java調優時,首先要考慮的是阻塞隊列大小的設置。根據不同的應用場景,可以選擇不同大小的隊皮芹列,有效地調整系統性能。例如,如果應用程序的任務量較大,就要選擇增大阻塞隊列的大小,以減少任務的等待和擁塞情況;如果應用程序的任務核握頌量少,則可以選擇減小隊列的大小,以節省內存的使用。
⑥ java線程阻塞問題,怎麼解決
典型地,suspend() 和 resume() 被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生後,讓線程阻塞,另一個線程產生了結果後,調用 resume() 使其恢復。但suspend()方法很容易引起死鎖問題,已經不推薦使用了。wait() 和 notify() 方法:兩塵早穗個方法配套使用,wait() 使得線程進入阻塞狀態,它有兩種形式,一種允許 指定以毫秒為單位的一段時間作為參數,另一種沒有參數,前者當對應的 notify() 被調用或者超出指定時間時線程重新進入可執行狀態,後者則必須對應的 notify() 被調用。 初看起來它們與 suspend() 和 resume() 方法對沒有什麼分別,但是事實上它們是截然不同的。區別的核心在於,前面敘述的所有方法,阻塞時都不會釋放佔用的鎖(如果佔用了的話),派卜而這一對方法則相反。 上述的核心區別導致了一系列的細節上的區別。 首先,前面敘述的所有方法都隸屬於 Thread 類,但是這一對卻直接隸屬於 Object 類,也就是說,所有對象都擁有這一對方法。初看起來這十分不可思議,但是實際上卻是很自然的,因為這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具有的,調用任意對象的 wait() 方法導致線程阻塞,並且該對象上的鎖被釋放。而調用 任意對象的notify()方法則導致因調用該對象的 wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖後才真正可執行)。 其次,前面敘述的所有方法都可在任何位置調用,但是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在 synchronized 方法或塊中當前線程才佔有鎖,才有鎖可以釋放。同樣的道理,調用這一對方法的對象上的鎖必須為當前線程所擁有,這樣才有鎖可以釋放。因此,這一對方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的上鎖對象就是調用這一對方法的對象。若不滿足這一條件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。 wait() 和 notify() 方法的上述特性決定了它們經常和synchronized 方法或塊一起使用,將它們和操作系統的進程間通信機製作一個比較就會發現它們的相似性:synchronized方法或塊提供了類似於操作系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則相當於 block 和wakeup 原語(這一對方法均聲明為 synchronized)。它們的結合使得我們可以實現操作系統上一系列精妙的進程間通信的演算法(如信號量睜嘩演算法),並用於解決各種復雜的線程間通信問題。 關於 wait() 和 notify() 方法最後再說明兩點: 第一:調用 notify() 方法導致解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,我們無法預料哪一個線程將會被選擇,所以編程時要特別小心,避免因這種不確定性而產生問題。 第二:除了 notify(),還有一個方法 notifyAll() 也可起到類似作用,唯一的區別在於,調用 notifyAll() 方法將把因調用該對象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當然,只有獲得鎖的那一個線程才能進入可執行狀態。 談到阻塞,就不能不談一談死鎖,略一分析就能發現,suspend() 方法和不指定超時期限的 wait() 方法的調用都可能產生死鎖。遺憾的是,Java 並不在語言級別上支持死鎖的避免,我們在編程中必須小心地避免死鎖。 以上我們對 Java 中實現線程阻塞的各種方法作了一番分析,我們重點分析了 wait() 和 notify() 方法,因為它們的功能最強大,使用也最靈活,但是這也導致了它們的效率較低,較容易出錯。實際使用中我們應該靈活使用各種方法,以便更好地達到我們的目的。
⑦ java中的阻塞式方法是什麼意思,比如InputStream中的read()方法。
這個阻塞的意思就是說: 程序一直停在read()方法這里,等待數據。沒有數據就不繼續往下執行,直到得到數據。明白了吧。
⑧ Java多線程: 如何阻塞和繼續線程運行 (轉)
典型地,suspend() 和 resume() 被用在等待另一個線程產生的結果的情形:測試發現結果還沒有產生後,讓線程阻塞,另一個線程產生了結果後,調用 resume() 使其恢復。但suspend()方法很容易引起死鎖問題,已經不推薦使用了。wait() 和 notify() 方法:兩個方法配套使用,wait() 使得線程進入阻塞狀態,它有兩種形式,一種允許 指定以毫秒為單位的一段時間作為參數,另一種沒有參數,前者當對應的 notify() 被調用或者超出指定時間時線程重新進入可執行狀態,後者則必須對應的 notify() 被調用。 初看起來它們與 suspend() 和 resume() 方法對沒有什麼分別,但是事實上它們是截然不同的。區別的核心在於,前面敘述的所有方法,阻塞時都不會釋放佔用的鎖(如果佔用了的話),而這一對方法則相反。 上述的核心區別導致了一系列的細節上的區別。 首先,前面敘述的所有方法都隸屬於 Thread 類,但是這一對卻直接隸屬於 Object 類,也就是說,所有對象都擁有這一對方法。初看起來這十分不可思議,但是實際上卻是很自然的,因為這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具有的,調用任意對象的 wait() 方法導致線程阻塞,並且該對象上的鎖被釋放。而調用 任意對象的notify()方法則導致因調用該對象的 wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖後才真正可執行)。 其次,前面敘述的所有方法都可在任何位置調用,但是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在 synchronized 方法或塊中當前線程才佔有鎖,才有鎖可以釋放。同樣的道理,調用這一對方法的對象上的鎖必須為當前線程所擁有,這樣才有鎖可以釋放。因此,這一對方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的上鎖對象就是調用這一對方法的對象。若不滿足這一條件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。 wait() 和 notify() 方法的上述特性決定了它們經常和synchronized 方法或塊一起使用,將它們和操作系統的進程間通信機製作一個比較就會發現它們的相似性:synchronized方法或塊提供了類似於操作系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則相當於 block 和wakeup 原語(這一對方法均聲明為 synchronized)。它們的結合使得我們可以實現操作系統上一系列精妙的進程間通信的演算法(如信號量演算法),並用於解決各種復雜的線程間通信問題。 關於 wait() 和 notify() 方法最後再說明兩點: 第一:調用 notify() 方法導致解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,我們無法預料哪一個線程將會被選擇,所以編程時要特別小心,避免因這種不確定性而產生問題。 第二:除了 notify(),還有一個方法 notifyAll() 也可起到類似作用,唯一的區別在於,調用 notifyAll() 方法將把因調用該對象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當然,只有獲得鎖的那一個線程才能進入可執行狀態。 談到阻塞,就不能不談一談死鎖,略一分析就能發現,suspend() 方法和不指定超時期限的 wait() 方法的調用都可能產生死鎖。遺憾的是,Java 並不在語言級別上支持死鎖的避免,我們在編程中必須小心地避免死鎖。 以上我們對 Java 中實現線程阻塞的各種方法作了一番分析,我們重點分析了 wait() 和 notify() 方法,因為它們的功能最強大,使用也最靈活,但是這也導致了它們的效率較低,較容易出錯。實際使用中我們應該靈活使用各種方法,以便更好地達到我們的目的。
⑨ java中如何使一個線程進入阻塞態
假設你有一個主線程,線程名為:Thread_A,然後通過Thread_A創建了線程Thread_B、Thread_C,並將線程Thread_B、Thread_C作為局部變數的方式存儲在Thread_A中,並調用Thread_B、Thread_C的start()方法開始執行Thread_B、Thread_C,當Thread_A執行到你要停止的地方就分別調用Thread_B、Thread_C的Wait()方法,使Thread_B、Thread_C暫停,然後線程Thread_A繼續執行,直到Thread_A中調用Thread_B、Thread_C的notify()方法使得Thread_B、Thread_C繼續執行,大體上就是這樣!