㈠ Queue 存入 和 取出 是線程安全的嗎
Queue本身並不是線程安全的, 有兩種方法來保證線程安全:
1. 手動加鎖。
Queue myCollection = new Queue();
lock(myCollection.SyncRoot)
{
foreach (object item in myCollection)
{
// Insert your code here.
}
}
2. 調用Synchronized方法,這時候得到的就是一個線程安全的Queue
Queue mySyncdQ = Queue.Synchronized( myQ );
㈡ java開發中線程的安全問題以及產生的原因
Java如何保證原子性常用的保證Java操作原子性的工具是鎖和同步方法(或者同步代碼塊)。使用鎖,可以保證同一時間只有一個線程能拿到鎖,也就保證了同一時間只有一個線程能執行申請鎖和釋放鎖之間的代碼。
與鎖類似的是同步方法或者同步代碼塊。使用非靜態同步方法時,鎖住的是當前實例;使用靜態同步方法時,鎖住的是該類的Class對象;使用靜態代碼塊時,鎖住的是synchronized關鍵字後面括弧內的對象。
㈢ 如何解決java中線程安全問題
java中,線程安全的解決方法或過程:
1.如果對象是immutable,則是線程安全的,例如:String,可以放心使用。
2. 如果對象是線程安全的,則放心使用。
3.有條件線程安全,對於Vector和Hashtable一般情況下是線程安全的,但是對於某些特殊情況,需要通過額外的synchronized保證線程安全。
4.使用synchronized關鍵字。
㈣ java priorityblockingqueue 線程安全嗎
必須的,concurrent提供的xxxBlockingQueue都是線程安全的
㈤ java中的queue類有哪些用法
java中的queue類是隊列數據結構管理類。在它里邊的元素可以按照添加它們的相同順序被移除。
隊列通常(但並非一定)以 FIFO(先進先出)的方式排序各個元素。不過優先順序隊列和 LIFO 隊列(或堆棧)例外,前者根據提供的比較器或元素的自然順序對元素進行排序,後者按 LIFO(後進先出)的方式對元素進行排序。無論使用哪種排序方式,隊列的頭都是調用remove()或poll()所移除的元素。在 FIFO 隊列中,所有的新元素都插入隊列的末尾。其他種類的隊列可能使用不同的元素放置規則。每個Queue實現必須指定其順序屬性。
offer 添加一個元素並返回true 如果隊列已滿,則返回false
poll 移除並返問隊列頭部的元素 如果隊列為空,則返回null
peek 返回隊列頭部的元素 如果隊列為空,則返回null
put 添加一個元素 如果隊列滿,則阻塞
take 移除並返回隊列頭部的元素 如果隊列為空,則阻塞
element 返回隊列頭部的元素 如果隊列為空,則拋出一個NoSuchElementException異常
add 增加一個元索 如果隊列已滿,則拋出一個IIIegaISlabEepeplian異常
remove 移除並返回隊列頭部的元素 如果隊列為空,則拋出一個
NoSuchElementException異常
注意:poll和peek方法出錯進返回null。因此,向隊列中插入null值是不合法的。
還有帶超時的offer和poll方法重載,例如,下面的調用:
boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);
嘗試在100毫秒內向隊列尾部插入一個元素。如果成功,立即返回true;否則,當到達超時進,返回false。同樣地,調用:
Object head = q.poll(100, TimeUnit.MILLISECONDS);
如果在100毫秒內成功地移除了隊列頭元素,則立即返回頭元素;否則在到達超時時,返回null。
阻塞操作有put和take。put方法在隊列滿時阻塞,take方法在隊列空時阻塞。
Queue介面與List、Set同一級別,都是繼承了Collection介面。LinkedList實現了Queue接 口。Queue介面窄化了對LinkedList的方法的訪問許可權(即在方法中的參數類型如果是Queue時,就完全只能訪問Queue介面所定義的方法 了,而不能直接訪問 LinkedList的非Queue的方法),以使得只有恰當的方法才可以使用。BlockingQueue 繼承了Queue介面。
㈥ java 如何實現一個線程安全的隊列
以下是兩個線程:
import java.util.*;
public class Thread_List_Operation {
//假設有這么一個隊列
static List list = new LinkedList();
public static void main(String[] args) {
Thread t;
t = new Thread(new T1());
t.start();
t = new Thread(new T2());
t.start();
}
}
//線程T1,用來給list添加新元素
class T1 implements Runnable{
void getElemt(Object o){
Thread_List_Operation.list.add(o);
System.out.println(Thread.currentThread().getName() + "為隊列添加了一個元素");
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
getElemt(new Integer(1));
}
}
}
//線程T2,用來給list添加新元素
class T2 implements Runnable{
void getElemt(Object o){
Thread_List_Operation.list.add(o);
System.out.println(Thread.currentThread().getName() + "為隊列添加了一個元素");
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
getElemt(new Integer(1));
}
}
}
//結果(亂序)
Thread-0為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-1為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
Thread-0為隊列添加了一個元素
㈦ Java中如何保證線程安全性
並發(concurrency)一個並不陌生的詞,簡單來說,就是cpu在同一時刻執行多個任務。
而Java並發則由多線程實現的。
在jvm的世界裡,線程就像不相乾的平行空間,串列在虛擬機中。(當然這是比較籠統的說法,線程之間是可以交互的,他們也不一定是串列。)
多線程的存在就是壓榨cpu,提高程序性能,還能減少一定的設計復雜度(用現實的時間思維設計程序)。
這么說來似乎線程就是傳說中的銀彈了,可事實告訴我們真正的銀彈並不存在。
多線程會引出很多難以避免的問題, 如死鎖,臟數據,線程管理的額外開銷,等等。更大大增加了程序設計的復雜度。
但他的優點依舊不可替代。
死鎖和臟數據就是典型的線程安全問題。
簡單來說,線程安全就是:在多線程環境中,能永遠保證程序的正確性。
只有存在共享數據時才需要考慮線程安全問題。
java內存區域:
其中,方法區和堆就是主要的線程共享區域。那麼就是說共享對象只可能是類的屬性域或靜態域。
了解了線程安全問題的一些基本概念後, 我們就來說說如何解決線程安全問題。我們來從一個簡單的servlet示例來分析:
1. 了解業務場景的線程模型
這里的線程模型指的是: 在該業務場景下, 可能出現的線程調用實況。
眾所周知,Servlet是被設計為單實例,在請求進入tomcat後,由Connector建立連接,再講請求分發給內部線程池中的Processor,
此時Servlet就處於一個多線程環境。即如果存在幾個請求同時訪問某個servlet,就可能會有幾個線程同時訪問該servlet對象。如圖:
線程模型,如果簡單的話,就在腦海模擬一下就好了,復雜的話就可以用紙筆或其他工具畫出來。
2. 找出共享對象
這里的共享對象就很明顯就是ReqCounterServlet。
3. 分析共享對象的不變性條件
不變性條件,這個名詞是在契約式編程的概念中的。不變性條件保證類的狀態在任何功能被執行後都保持在一個可接受的狀態。
這里可以引申出,不可變對象是線程安全的。(因為不可變對象就沒有不變性條件)
不變性條件則主要由對可變狀態的修改與訪問構成。
這里的servlet很簡單, 不變性條件大致可以歸納為: 每次請求進入時count計數必須加一,且計數必須正確。
在復雜的業務中, 類的不變性條件往往很難考慮周全。設計的世界是險惡的,只能小心謹慎,用測量去證明,最大程度地減少錯誤出現的幾率。
4. 用特定的策略解決線程安全問題。
如何解決的確是該流程的重點。目前分三種方式解決:
第一種,修改線程模型。即不在線程之間共享該狀態變數。一般這個改動比較大,需要量力而行。
第二種,將對象變為不可變對象。有時候實現不了。
第三種,就比較通用了,在訪問狀態變數時使用同步。 synchronized和Lock都可以實現同步。簡單點說,就是在你修改或訪問可變狀態時加鎖,獨占對象,讓其他線程進不來。
這也算是一種線程隔離的辦法。(這種方式也有不少缺點,比如說死鎖,性能問題等等)
其實有一種更好的辦法,就是設計線程安全類。《代碼大全》就有提過,問題解決得越早,花費的代價就越小。
是的,在設計時,就考慮線程安全問題會容易的多。
首先考慮該類是否會存在於多線程環境。如果不是,則不考慮線程安全。
然後考慮該類是否能設計為不可變對象,或者事實不可變對象。如果是,則不考慮線程安全
最後,根據流程來設計線程安全類。
設計線程安全類流程:
1、找出構成對象狀態的所有變數。
2、找出約束狀態變數的不變性條件。
3、建立對象狀態的並發訪問管理策略。
有兩種常用的並發訪問管理策略:
1、java監視器模式。 一直使用某一對象的鎖來保護某狀態。
2、線程安全委託。將類的線程安全性委託給某個或多個線程安全的狀態變數。(注意多個時,這些變數必須是彼此獨立,且不存在相關聯的不變性條件。)
㈧ 多線程的隊列blockqueue如何理解
在Java多線程應用中,隊列的使用率很高,多數生產消費模型的首選數據結構就是隊列。Java提供的線程安全的Queue可以分為阻塞隊列和非阻塞隊列,其中阻塞隊列的典型例子是BlockingQueue,非阻塞隊列的典型例子是ConcurrentLinkedQueue,在實際應用中要根據實際需要選用阻塞隊列或者非阻塞隊列。 註:什麼叫線程安全?這個首先要明確。線程安全就是說多線程訪問同一代碼,不會產生不確定的結果。 LinkedBlockingQueue 由於LinkedBlockingQueue實現是線程安全的,實現了先進先出等特性,是作為生產者消費者的首選,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的話,默認最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在隊列滿的時候會阻塞直到有隊列成員被消費,take方法在隊列空的時候會阻塞,直到有隊列成員被放進來。