1. java多線程並發去調用一個類的靜態方法,有什麼問題
總的結論:java是線程安全的,即對任何方法(包括靜態方法)都可以不考慮線程沖突,但有一個前提,就是不能存在全局變數。如果存在全局變數,則需要使用同步機制。x0dx0ax0dx0a如下通過一組對比例子從頭講解:x0dx0a 在多線程中使用靜態方法會發生什麼事?也就是說多線程訪問同一個類的static靜態方法會發生什麼事?是否會發生線程安全問題?x0dx0apublic class Test {x0dx0a public static void operation(){x0dx0a // ... do somethingx0dx0a }x0dx0a}x0dx0a 事實證明只要在靜態函數中沒有處理多線程共享數據,就不存在著多線程訪問同一個靜態方法會出現資源沖突的問題。下面看一個例子:x0dx0apublic class StaticThread implements Runnable {x0dx0a @Overridex0dx0a public void run() {x0dx0a // TODO Auto-generated method stubx0dx0a StaticAction.print();x0dx0a }x0dx0a public static void main(String[] args) {x0dx0a for (int i = 0; i < 100; i++) {x0dx0a new Thread(new StaticThread()).start();x0dx0a }x0dx0a }x0dx0a}x0dx0apublic class StaticAction {x0dx0a public static int i = 0;x0dx0a public static void print() {x0dx0a int sum = 0;x0dx0a for (int i = 0; i < 10; i++) {x0dx0a System.out.print("step " + i + " is running.");x0dx0a sum += i;x0dx0a }x0dx0a if (sum != 45) {x0dx0a System.out.println("Thread error!");x0dx0a System.exit(0);x0dx0a }x0dx0a System.out.println("sum is " + sum);x0dx0a }x0dx0a}x0dx0a 實際執行的結果顯示各個線程對靜態方法的訪問是交叉執行的,但是這並不影響各個線程靜態方法print()中sum值的計算。也就是說,在此過程中沒有使用全局變數的靜態方法在多線程中是安全的,靜態方法是否引起線程安全問題主要看該靜態方法是否對全局變數(靜態變數static member)進行修改操作。x0dx0a 在多線程中使用同一個靜態方法時,每個線程使用各自的實例欄位(instance field)的副本,而共享一個靜態欄位(static field)。所以說,如果該靜態方法不去操作一個靜態成員,只在方法內部使用實例欄位(instance field),不會引起安全性問題。x0dx0a 但是,如果該靜態方法操作了一個靜態變數,則需要靜態方法中採用互斥訪問的方式進行安全處理。我們來看一下沒有使用互斥訪問的話會產生怎樣的問題:public class StaticAction {x0dx0a public static int i = 0;x0dx0a public static void incValue() {x0dx0a int temp = StaticAction.i;x0dx0a try {x0dx0a Thread.sleep(1);x0dx0a } catch (Exception e) {x0dx0a e.printStackTrace();x0dx0a }x0dx0a temp++;x0dx0a StaticAction.i = temp;x0dx0a }x0dx0a}x0dx0apublic class StaticThread implements Runnable {x0dx0a @Overridex0dx0a public void run() {x0dx0a // TODO Auto-generated method stubx0dx0a StaticAction.incValue();x0dx0a }x0dx0a public static void main(String[] args) {x0dx0a for (int i = 0; i < 100; i++) {x0dx0a new Thread(new StaticThread()).start();x0dx0a }x0dx0a try {x0dx0a Thread.sleep(1000); //預留足夠的時間讓上面的線程跑完x0dx0a } catch (Exception e) {x0dx0a e.printStackTrace();x0dx0a }x0dx0a System.out.println(StaticAction.i);x0dx0a }x0dx0a}x0dx0a 實際運行結果顯示i值為隨機的數字。為了實現互斥訪問,這時我們需要加入一個synchronized關鍵字。代碼修改如下:x0dx0apublic class StaticAction {x0dx0a public static int i = 0;x0dx0a public synchronized static void incValue() {x0dx0a int temp = StaticAction.i;x0dx0a try {x0dx0a Thread.sleep(1);x0dx0a } catch (Exception e) {x0dx0a e.printStackTrace();x0dx0a }x0dx0a temp++;x0dx0a StaticAction.i = temp;x0dx0a }x0dx0a}x0dx0apublic class StaticThread implements Runnable {x0dx0a @Overridex0dx0a public void run() {x0dx0a // TODO Auto-generated method stubx0dx0a StaticAction.incValue();x0dx0a }x0dx0a public static void main(String[] args) {x0dx0a for (int i = 0; i < 100; i++) {x0dx0a new Thread(new StaticThread()).start();x0dx0a }x0dx0a try {x0dx0a Thread.sleep(1000);x0dx0a } catch (Exception e) {x0dx0a e.printStackTrace();x0dx0a }x0dx0a System.out.println(StaticAction.i);x0dx0a }x0dx0a}x0dx0a 運行結果則必然是100。x0dx0a 加入synchronized關鍵字的靜態方法稱為同步靜態方法。x0dx0a 在訪問同步靜態方法時,會獲取該類的「Class」對象,所以當一個線程進入同步的靜態方法中時,線程監視器獲取類本身的對象鎖,其它線程不能進入這個類的任何靜態同步方法。它不像實例方法,因為多個線程可以同時訪問不同實例同步實例方法。這個其實就是操作系統中的用信號量實現進程的互斥與同步問題,如果涉及在同一個類中有多個靜態方法中處理多線程共享數據的話,那就變成用信號量解決生產者-消費者問題。也就是說,靜態方法是一份臨界資源,對靜態方法的訪問屬於進入臨界區;對靜態變數的修改是一份臨界資源,對靜態變數的修改屬於進入臨界區。
2. java如何實現靜態變數多線程安全問題
public class A { public void method01(){ //dosomething } public void method02(){ //dosomething } //public void method03(){ public static void method03(){ // 靜態方法里才可以有今天變數 static Map map = new TreeMap(); static String x=「」; // 如果你的 method4,5,6是非同步的, 5,6得到的值就是不確定的, // 有可能是4之前的值,也有可能是4的賦值 method4(){ 這裡面會給map和x賦值 } method5(){ 這裡面會用到map和x } method6(){ 這裡面會用到map和x } }}
3. Java中關於static成員方法的線程安全問題
都同時調用了,怎麼還不是多線環境睜爛下呢?但是就算是同時調用,如果沒有共享變數,有共享變鋒早改量,但變數是final(引用類型除外)或者是線程安全類(Concurrent包下的,也可以)就不會存在並發問題。
public
class
TestUtil()
{
private
static
int
i
=
0
public
static
int
a
(){
return
i++;//會有並發問題
}
public
static
int
b()
{
int
i
=
0;
return
i++;//不會有並發問題
}
}
方法是否存在並發問題,判斷是否有競態條件就銀判好了
4. java中多線程中的static和voilate
static不能實現多線程共享,它的作用是讓同一個類的不同對象,共用同一個變數,與線程無關。如果有多個線程同時修改一個靜態變數,同樣會有不同步問題。
5. 初學Java多線程:使用Synchronized塊同步方法
synchronized關鍵字有兩種用法 第一種就是在《使用Synchronized關鍵字同步類方法》一文中所介紹的直接用在方法的定義中 另外一種就是synchronized塊 我們不僅可以通過synchronized塊來同步一個對象變數巧頃 也可以使用synchronized塊來同步類中的靜態孝寬陸方法和非靜態方法
synchronized塊的語法如下
public void method()
{
… …
synchronized(表達式)
{
… …
}
}
一 非靜態類方法的同步
從《使用Synchronized關鍵字同步類方法》一文中我們知道使用synchronized關鍵字來定義方法就會鎖定類中所有使用synchronzied關鍵字定義的靜態方法或非靜態方法 但這並不好理解 而如果使用synchronized塊來達到同樣的效果 就不難理解為什麼會產生這種效果了 如果想使用synchronized塊來鎖定類中所有的同步非靜態方法 需要使用this做為synchronized塊的參數傳入synchronized塊國 代碼如下
通過synchronized塊同步非靜態方法
public class SyncBlock
{
public void method ()
{
synchronized(this) // 相當於對method 方法使用synchronized關鍵字
{
… …
}
}
public void method ()
{
synchronized(this) // 相當於對method 方法使用synchronized關鍵字
{
… …
}
}
public synchronized void method ()
{
… …
}
}
在上面的代碼中的method 和method 方法中使用了synchronized塊 而第 行的method 方法仍然使用synchronized關鍵字來定義方法 在使用同一個SyncBlock類實例時 這三個方法只要有一個正在執行 其他兩個方法就會因未獲得同步鎖而被阻塞 在使用synchronized塊時要想達到和synchronized關鍵字同樣的效果 必須將所有的代碼都寫在synchronized塊中 否則 將無法使當前方法中的所有代碼和其他的方法同步
除了使用this做為synchronized塊的參數外 還可以使用SyncBlock this作為synchronized塊的參數來達到同樣的效果
在內類(InnerClass)的方法中使用synchronized塊來時 this只表示內類 和外類(OuterClass)沒有關系 但內類的非靜態方法可以和外類的非靜態方法同步 如在內類InnerClass中加一個method 方法 並使method 方法和SyncBlock的三個方法同步 代碼如下
使內類的非靜態方法和外類的非靜態方法同步
public class SyncBlock
{
… …
class InnerClass
{
public void method ()
{
synchronized(SyncBlock this)
{
… …
}
}
}
… …
}
在上面SyncBlock類的新版本中 InnerClass類的method 方法和SyncBlock類的其他三個方法同步 因此 method method method 和method 四個方法在同一時間巧手只能有一個方法執行
Synchronized塊不管是正常執行完 還是因為程序出錯而異常退出synchronized塊 當前的synchronized塊所持有的同步鎖都會自動釋放 因此 在使用synchronized塊時不必擔心同步鎖的釋放問題
二 靜態類方法的同步
由於在調用靜態方法時 對象實例不一定被創建 因此 就不能使用this來同步靜態方法 而必須使用Class對象來同步靜態方法 代碼如下
通過synchronized塊同步靜態方法
public class StaticSyncBlock
{
public static void method ()
{
synchronized(StaticSyncBlock class)
{
… …
}
}
public static synchronized void method ()
{
… …
}
}
在同步靜態方法時可以使用類的靜態欄位class來得到Class對象 在上例中method 和method 方法同時只能有一個方法執行 除了使用class欄位得到Class對象外 還可以使用實例的getClass方法來得到Class對象 上例中的代碼可以修改如下
使用getClass方法得到Class對象
public class StaticSyncBlock
{
public static StaticSyncBlock instance;
public StaticSyncBlock()
{
instance = this;
}
public static void method ()
{
synchronized(instance getClass())
{
}
}
}
在上面代碼中通過一個public的靜態instance得到一個StaticSyncBlock類的實例 並通過這個實例的getClass方法得到了Class對象(一個類的所有實例通過getClass方法得到的都是同一個Class對象 因此 調用任何一個實例的getClass方法都可以) 我們還可以通過Class對象使不同類的靜態方法同步 如Test類的靜態方法method和StaticSyncBlock類的兩個靜態方法同步 代碼如下
Test類的method方法和StaticSyncBlock類的method method 方法同步
public class Test
{
public static void method()
{
synchronized(StaticSyncBlock class)
{
}
}
}
lishixin/Article/program/Java/gj/201311/27374
6. java多線程中,如何給靜態變數(如List)加鎖/同步
使用synchronized關鍵字同步方法就可以了。
public class Foo2 {
private int x = 100;
public int getX() {
return x;
}
//同步方法
public synchronized int fix(int y) {
x = x - y;
System.out.println("線程"+Thread.currentThread().getName() + "運行結束,減少「" + y + "」,當前值為:" + x);
return x;
}
}
7. java多線程調用靜態方法安全嗎
這要看靜態方法中有沒有操作靜態成員變數了,看代碼吧
{
staticintnum=0;
publicstaticvoidaddOne()throwsInterruptedException{
for(inti=0;i<=10;i++){
num+=i;
}
System.out.println(Thread.currentThread().getName()+"-"+num);
num=0;
}
}
如上面代碼所示,當單線程運行情況下是輸出正常的,num最後應該輸出55,但是在多線程情況下,則會出現每個線程輸出的num不一樣的情況,這是因為num是靜態成員變數,為多個線程所共享的,有可能會出現一個線程的num值還沒有重新賦值為0,另外一個線程已經讀取到num的累加後的值,所以說,多線程情況下,靜態方法中如果操作靜態成員變數,那這個靜態方法就不是線程安全的
8. JAVA中當多個線程同步調用static方法或static變數的時候會產生沖突嗎
靜態塊的資源訪問謹物信消時不會有沖突的,
單例么,比如車場是單例祥坦液的,但是裡面有很多車,每個客戶來都可以分配單獨的一輛車,所以多線程同步 也是不會沖突的
9. 初學Java的關鍵主要是什麼
在計算機快速發展的今天,計算機行業的人才需求量也是越來越多,很多人開始選擇從計算機方法進行發展。很多人都知道,計算機方面的知識是比較復雜的,學習起來會遇到很多的困難,Java語言是軟體開發中使用最多的語言,那麼對於初學者應該如何進行選擇呢?學習Java語言開發的過程中,什麼是最關鍵的?應該如何進行學習?下面電腦培訓為大家介紹初學Java的關鍵。
一、學習靜態方法和屬性
在學習Java開發中,靜態語言和屬性的使用是非常關鍵的,主要是用於描述某一類對象群體的特徵,而不是屬於單個對象的特徵。在Java中需要大量的使用靜態方法和屬性,這個技巧是非常關鍵的,但是有一個缺點就是這種語言不能被頻繁的使用。在學習過程中,靜態方法和屬性對於後期理解類和對象內容有很大的幫助,在進行Java開發時,靜態方法和屬性的使用是非常頻繁的。
二、重視介面問題
類繼承在早期面向對象的應用程序中大量使用。隨著軟體工程理論的不斷發展,人們開始意識到繼承的諸多缺點,並開始嘗試使用聚合而不是繼承。IT培訓認為能夠很好的解決可擴展性的軟體工程的重要原則的抽象描述,並且還能直接使用的工具是界面。介面已經逐漸成為近年來Java編程的核心。
三、集合框架的學習
Java進行描述復雜數據結構的主要方式是集合框架。Java沒有任何指針,而是復雜數據結構的復雜集合,例如數組和對象數組。學習這些數據結構的描述對於應正滑悔用程序編程至關重要,特別是在涉及伺服器端的3層結構編程時。此時,昌平北大青鳥發現舉正可能出現程序員無法再使用諸如資料庫結果集之類的結構來描述數據的情況。
四、多線程的理解機理
在進行學習Java語言的時候,很多人對多線程程序的編寫非常感興趣,畢竟這是對邏輯能力最大的挑戰。但是在進行開發的過程中,其實很多應用都會不需要使用多線程程序,並且很多厲害的應用程序員在編寫代碼的過程中也是不需要使用多線程的。一般情況下讓悶,北大青鳥北京計算機學院發現多線程機制主要是使用到基礎平台中。
10. JAVA中static 方法在多線程環境下的運用,求解。
static相當與在你的系統內存開辟出一塊固定內存,整個項目都可以訪問並且修改他
比如 static int a=0;
假設同時開啟3個線層
你在線層a裡面核慧a=1;
線程b:a=2;
線程c:a=3;
因睜或為我們並不知道那個線程會悉氏伍最後結束 所以沒辦法判斷a=?