Java靜態(tài)方法是使用公共內存空間的,就是說(shuō)所有對象都可以引用,而且在沒(méi)有創(chuàng )建對象時(shí)也可以利用類(lèi)使用該方法。
例如,我創(chuàng )建一個(gè)類(lèi),里面有一個(gè)靜態(tài)方法:
class Test{
public static int z(int xx,int yy){
return xx+yy;
}
public int zz(int xx,int yy){
return xx+yy;
}
}
然后在含有main方法的類(lèi)中使用這個(gè)類(lèi)時(shí),對與以上非靜態(tài)和靜態(tài)方法的引用方式是不同的,如下:
import Test;
public class mainClass{
int sum;
public static void main(String args[]){
sum=Test.z(1,2); //直接用 類(lèi).方法或者屬性就可以使用該方法或屬性。
System.out.println(sum);
Test t=new Test();
sum=t.zz(1,2); //因為zz不是靜態(tài)方法,所以只能只能用Test類(lèi)創(chuàng )建一個(gè)t對象,然后調用該對象的方法。
System.out.println(sum);
}
}
靜態(tài)方法可以調用靜態(tài)方法,但不能調用成員方法。
wait():使一個(gè)線(xiàn)程處于等待狀態(tài),并且釋放所持有的對象的lock。
sleep():使一個(gè)正在運知行的線(xiàn)程處于睡眠狀態(tài),是一個(gè)靜態(tài)方法,調用此道方法要捕捉InterruptedException異常。
notify():?jiǎn)拘岩粋€(gè)處于等待狀態(tài)的線(xiàn)程,注意的是在調用此方法的時(shí)候,并不專(zhuān)能確切的喚醒某一個(gè)等待狀態(tài)的線(xiàn)程,而是由JVM確定喚醒哪個(gè)線(xiàn)程,而且不是按優(yōu)先級。
Allnotity():?jiǎn)拘阉刑幦氲却隣顟B(tài)的線(xiàn)程,注意并不是給所有喚醒線(xiàn)程一個(gè)對象的鎖,而是讓屬它們競爭。
靜態(tài)方法、靜態(tài)變量,方便了開(kāi)發(fā)中的操作,不需要實(shí)例則可以調用,但是往往卻破壞了一些屬性的封裝,使得在安全性方面大大降低,在內存使用上和實(shí)例變量有著(zhù)不同的地方,靜態(tài)變量或方法他是在程序一運行類(lèi)一加載的時(shí)候就會(huì )為他分配了一塊內存地址,相當于初始化了這些靜態(tài)變量,而實(shí)例變量或屬性是只有當對象被實(shí)例的時(shí)候才會(huì )為這些屬性分配地址,也就是說(shuō)在程序運行的時(shí)候,如果是小程序,那么在使用過(guò)程中占用的內存會(huì )隨著(zhù)你實(shí)例的創(chuàng )建而逐步增加,對象需要被共享的時(shí)候,這時(shí)候可以考慮單例模式(只有一個(gè)實(shí)例),保證不會(huì )浪費內存地址,當然這要符合實(shí)際,但是如果是一個(gè)比較大的項目,重用性強,變量需要被共享的時(shí)候,就可以考慮用static來(lái)解決。
可以多多交流哦 交流群:45271133。
總的結論:java是線(xiàn)程安全的,即對任何方法(包括靜態(tài)方法)都可以不考慮線(xiàn)程沖突,但有一個(gè)前提,就是不能存在全局變量。如果存在全局變量,則需要使用同步機制。
如下通過(guò)一組對比例子從頭講解:
在多線(xiàn)程中使用靜態(tài)方法會(huì )發(fā)生什么事?也就是說(shuō)多線(xiàn)程訪(fǎng)問(wèn)同一個(gè)類(lèi)的static靜態(tài)方法會(huì )發(fā)生什么事?是否會(huì )發(fā)生線(xiàn)程安全問(wèn)題?
public class Test {
public static void operation(){
// 。 do something
}
}
事實(shí)證明只要在靜態(tài)函數中沒(méi)有處理多線(xiàn)程共享數據,就不存在著(zhù)多線(xiàn)程訪(fǎng)問(wèn)同一個(gè)靜態(tài)方法會(huì )出現資源沖突的問(wèn)題。下面看一個(gè)例子:
public class StaticThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
StaticAction.print();
}
public static void main(String[] args) {
for (int i = 0; i
在java5以前實(shí)現多線(xiàn)程有兩種方法(繼承Thread類(lèi)和實(shí)現Runnable接口)
它們分別為:
使用new Thread()和new Thread(Runnable)形式
第一種直接調用thread的run方法,所以,往往使用Thread子類(lèi),即new SubThread()。
第二種調用
Runnable的run方法。
第一種:
new Thread(){}.start();這表示調用Thread子類(lèi)對象的run方法,new Thread(){}表示一個(gè)Thread的匿名子類(lèi)的實(shí)例對象,子類(lèi)加上run方法后的代碼如下:
new Thread(){
public void run(){
}
}.start();
第二種:
new Thread(
new Runnable(){}
).start();
這表示調用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個(gè)Runnable的匿名子類(lèi)的實(shí)例對象,
runnable的子類(lèi)加上run方法后的代碼如下:
new Thread(new Runnable(){
public void run(){
}
}
).start();
類(lèi)的成員分為兩類(lèi),靜態(tài)成員(static member)和實(shí)例成員(instance member)。靜態(tài)成員屬于類(lèi),實(shí)例成員則屬于對象,即類(lèi)的實(shí)例。
簡(jiǎn)單討論一下在一個(gè)類(lèi)中使用靜態(tài)字段(static field)和靜態(tài)方法(static method)是否會(huì )有線(xiàn)程安全問(wèn)題。
我們在知道, 靜態(tài)字段(static field)和靜態(tài)方法(static method)的調用是通過(guò)類(lèi)來(lái)調用。靜態(tài)方法不對特定的實(shí)例操作,只能訪(fǎng)問(wèn)靜態(tài)成員。實(shí)例方法可對特定的實(shí)例操作,既能訪(fǎng)問(wèn)靜態(tài)成員,也能訪(fǎng)問(wèn)實(shí)例成員。
那么,在多線(xiàn)程中使用靜態(tài)方法是否有線(xiàn)程安全問(wèn)題?這要看靜態(tài)方法是是引起線(xiàn)程安全問(wèn)題要看在靜態(tài)方法中是否使用了靜態(tài)成員。
因為,在多線(xiàn)程中使用同一個(gè)靜態(tài)方法時(shí),每個(gè)線(xiàn)程使用各自的實(shí)例字段(instance field)的副本,而共享一個(gè)靜態(tài)字段(static field)。所以說(shuō),如果該靜態(tài)方法不去操作一個(gè)靜態(tài)成員,只在方法內部使用實(shí)例字段(instance field),不會(huì )引起安全性問(wèn)題。但是,如果該靜態(tài)方法操作了一個(gè)靜態(tài)字段,則需要靜態(tài)方法中采用互斥訪(fǎng)問(wèn)的方式進(jìn)行安全處理。
舉個(gè)簡(jiǎn)單的例子,我們使用的Console.WriteLine();中WriteLine()是Console.WriteLine類(lèi)的靜態(tài)方法。
對于A(yíng)SP.NET, 多個(gè)客戶(hù)端訪(fǎng)問(wèn)服務(wù)器端, 這是一個(gè)多線(xiàn)程的例子.只要理解了原因,我們可以在三層架構中的數據訪(fǎng)問(wèn)層中放心使用靜態(tài)方法(static method)來(lái)訪(fǎng)問(wèn)數據庫.
先看一個(gè)類(lèi):
public class Test
{
public static String hello(String str)
{
String tmp = "";
tmp = tmp + str;
return tmp;
}
}
hello方法會(huì )不會(huì )有多線(xiàn)程安全問(wèn)題呢?沒(méi)有!
靜態(tài)方法如果沒(méi)有使用靜態(tài)變量,則沒(méi)有線(xiàn)程安全問(wèn)題。
為什么呢?因為靜態(tài)方法內聲明的變量,每個(gè)線(xiàn)程調用時(shí),都會(huì )新創(chuàng )建一份,而不會(huì )共用一個(gè)存儲單元。比如這里的tmp,每個(gè)線(xiàn)程都會(huì )創(chuàng )建自己的一份,因此不會(huì )有線(xiàn)程安全問(wèn)題。
注意:靜態(tài)變量,由于是在類(lèi)加載時(shí)占用一個(gè)存儲區,每個(gè)線(xiàn)程都是共用這個(gè)存儲區的,所以如果在靜態(tài)方法里使用了靜態(tài)變量,這就會(huì )有線(xiàn)程安全問(wèn)題!
這要看靜態(tài)方法中有沒(méi)有操作靜態(tài)成員變量了,看代碼吧
public class StaticMethod implements Runnable {
static int num=0;
public static void addOne() throws InterruptedException {
for (int i = 0; i <= 10; i++) {
num += i;
}
System.out.println(Thread.currentThread().getName() + "-" + num);
num=0;
}
}如上面代碼所示,當單線(xiàn)程運行情況下是輸出正常的,num最后應該輸出55,但是在多線(xiàn)程情況下,則會(huì )出現每個(gè)線(xiàn)程輸出的num不一樣的情況,這是因為num是靜態(tài)成員變量,為多個(gè)線(xiàn)程所共享的,有可能會(huì )出現一個(gè)線(xiàn)程的num值還沒(méi)有重新賦值為0,另外一個(gè)線(xiàn)程已經(jīng)讀取到num的累加后的值,所以說(shuō),多線(xiàn)程情況下,靜態(tài)方法中如果操作靜態(tài)成員變量,那這個(gè)靜態(tài)方法就不是線(xiàn)程安全的
聲明:本網(wǎng)站尊重并保護知識產(chǎn)權,根據《信息網(wǎng)絡(luò )傳播權保護條例》,如果我們轉載的作品侵犯了您的權利,請在一個(gè)月內通知我們,我們會(huì )及時(shí)刪除。
蜀ICP備2020033479號-4 Copyright ? 2016 學(xué)習?shū)B(niǎo). 頁(yè)面生成時(shí)間:2.468秒