synchronized源碼
㈠ java中使用了synchronized還會出現重復數據
程序還沒試,不過一看 if (Thread.currentThread().getName() == "Thread-1") { 這樣的語句,就知道有問題了
第2個,synchronized (aa) {是不同的實例的,加synchronized 有什麼用呢
㈡ 怎麼閱讀spring源碼
從HttpServletBean的init()進入,再到initWebApplicationContext(),再到refresh(),再到refreshBeanFactory(),再到finishRefresh(),直到伺服器啟動成功。不知道讀了多少遍,
但是源碼的東西實在的太多了,想要完全讀懂,完全理清頭緒,還差很遠啊。所以我只重點關注了兩塊內容,就是bean的定位載入解析注冊、bean的實例化兩大塊內容,其他地方稍作了解,沒有太過深入。
整個容器的啟動流程,都在AbstractApplicationContext的refresh()的模板方法中了。
復制代碼
1 public void refresh() throws BeansException, IllegalStateException {
2 synchronized (this.startupShutdownMonitor) {
3 // Prepare this context for refreshing.
4 prepareRefresh();
5
6 // Tell the subclass to refresh the internal bean factory.
7 beanFactory = obtainFreshBeanFactory();
8
9 // Prepare the bean factory for use in this context.
10 prepareBeanFactory(beanFactory);
11
12 try {
13 // Allows post-processing of the bean factory in context subclasses.
14 postProcessBeanFactory(beanFactory);
15
16 // Invoke factory processors registered as beans in the context.
17 (beanFactory);
18
19 // Register bean processors that intercept bean creation.
20 registerBeanPostProcessors(beanFactory);
21
22 // Initialize message source for this context.
23 initMessageSource();
24
25 // Initialize event multicaster for this context.
26 ();
27
28 // Initialize other special beans in specific context subclasses.
29 onRefresh();
30
31 // Check for listener beans and register them.
32 registerListeners();
33
34 // Instantiate all remaining (non-lazy-init) singletons.
35 (beanFactory);
36
37 // Last step: publish corresponding event.
38 finishRefresh();
39 }
40
41 catch (BeansException ex) {
42 // Destroy already created singletons to avoid dangling resources.
43 destroyBeans();
44
45 // Reset 'active' flag.
46 cancelRefresh(ex);
47
48 // Propagate exception to caller.
49 throw ex;
50 }
51 }
52 }
其實,我並沒有上來就看源碼,而是先從看書開始,稍微了解,知道了一些關鍵點,關鍵流程,自己產生了一堆疑問,然後帶著疑問去讀源碼,讀著讀著,發現有些疑問就這么解決了。
㈢ arrayblockingqueue為什麼使用了lock而沒有使用synchronized
ArrayBlockingQueue 是JDK1.5才加進來的類,在JDK1.5 ReentrantLock 的應能遠遠好於Synchronized,不過在1.6以後,Synchronized 已經進行了優化,二者的性能已經差不了多少了。而且ReentrantLock支持Condition 可以實現特定喚醒操作,Synchronized 要麼喚醒一個或者所有都喚醒,這個特性對阻塞隊列的性能影響很大。
㈣ java源代碼分析 實在是不太會,求高手教教我。
packagetest2;
importjava.io.BufferedReader;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.IOException;
importjava.io.InputStream;
importjava.io.InputStreamReader;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Set;
publicclassJavaCodeAnalyzer{
publicstaticvoidanalyze(Filefile)throwsIOException{
//FileOutputStreamfos=newFileOutputStream("F;"+File.separator+"result.txt");
if(!(file.getName().endsWith(".txt")||file.getName().endsWith(".java"))){
System.out.println("輸入的分析文件格式不對!");
}
InputStreamis=newFileInputStream(file);
BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
Stringtemp;
intcount=0;
intcountSpace=0;
intcountCode=0;
intcountDesc=0;
Map<String,Integer>map=getKeyWords();
while((temp=br.readLine())!=null){
countKeys(temp,map);
count++;
if(temp.trim().equals("")){
countSpace++;
}elseif(temp.trim().startsWith("/*")||temp.trim().startsWith("//")){
countDesc++;
}else{
countCode++;
}
}
System.out.printf("代碼行數:"+countCode+"占總行數的%4.2f ",(double)countCode/count);
System.out.printf("空行數:"+countSpace+"占總行數的%4.2f ",(double)countSpace/count);
System.out.printf("注釋行數:"+countDesc+"占總行數的%4.2f ",(double)countDesc/count);
System.out.println("總行數:"+count);
System.out.println("出現最多的5個關鍵字是:");
System.out.println("");
System.out.println("");
System.out.println("");
System.out.println("");
System.out.println("");
}
publicstaticvoidmain(String[]args){
getKeyWords();
Filefile=newFile("F://Test.java");
try{
analyze(file);
}catch(IOExceptione){
//TODO自動生成catch塊
e.printStackTrace();
}
}
publicstaticMap<String,Integer>getKeyWords(){
Map<String,Integer>map=newHashMap<String,Integer>();
String[]keywords={"abstract","assert","boolean","break","byte","case","catch","char","class","continue","default","do","double","else","enum","extends","final","finally","float","for","if","implements","import","instanceof","int","interface","long","native","new","package","private","protected","public","return","strictfp","short","static","super","switch","synchronized","this","throw","throws","transient","try","void","volatile","while","goto","const"};
for(Strings:keywords){
map.put(s,0);
}
returnmap;
}
publicstaticvoidcountKeys(Strings,Map<String,Integer>map){
Set<String>keys=map.keySet();
for(Stringss:keys){
if(s.indexOf(ss)!=-1){
map.put(ss,map.get(ss)+1);
}
}
}
}
上班沒啥時間了,還有點沒寫完,你在想想。
㈤ jave語言的string字元串有哪些特點
以主流的 JDK 版本 1.8 來說,String 內部實際存儲結構為 char 數組,源碼如下:
publicfinalclassString
implementsjava.io.Serializable,Comparable<String>,CharSequence{
//用於存儲字元串的值privatefinalcharvalue[];
//緩存字元串的hashcodeprivateinthash;//Defaultto0
//......其他內容}
String源碼中包含下面幾個重要的方法。
1. 多構造方法
String 字元串有以下 4 個重要的構造方法:
//String為參數的構造方法publicString(Stringoriginal){
this.value=original.value;
this.hash=original.hash;
}//char[]為參數構造方法publicString(charvalue[]){
this.value=Arrays.Of(value,value.length);
}//StringBuffer為參數的構造方法publicString(StringBufferbuffer){
synchronized(buffer){
this.value=Arrays.Of(buffer.getValue(),buffer.length());
}
}//StringBuilder為參數的構造方法publicString(StringBuilderbuilder){
this.value=Arrays.Of(builder.getValue(),builder.length());
}
其中,比較容易被我們忽略的是以 StringBuffer 和 StringBuilder 為參數的構造函數,因為這三種數據類型,我們通常都是單獨使用的,所以這個小細節我們需要特別留意一下。
2. equals() 比較兩個字元串是否相等,源碼如下:
publicbooleanequals(ObjectanObject){
//對象引用相同直接返回trueif(this==anObject){
returntrue;
}
//判斷需要對比的值是否為String類型,如果不是則直接返回falseif(anObjectinstanceofString){
StringanotherString=(String)anObject;
intn=value.length;
if(n==anotherString.value.length){
//把兩個字元串都轉換為char數組對比charv1[]=value;
charv2[]=anotherString.value;
inti=0;
//循環比對兩個字元串的每一個字元while(n--!=0){
//如果其中有一個字元不相等就truefalse,否則繼續對比if(v1[i]!=v2[i])
returnfalse;
i++;
}
returntrue;
}
}
returnfalse;
}
String 類型重寫了 Object 中的 equals() 方法,equals() 方法需要傳遞一個 Object 類型的參數值,在比較時會先通過 instanceof 判斷是否為 String 類型,如果不是則會直接返回 false,instanceof 的使用如下:
ObjectoString="123";
ObjectoInt=123;
System.out.println(oStringinstanceofString);//返回trueSystem.out.println(oIntinstanceofString);//返回false
當判斷參數為 String類型之後,會循環對比兩個字元串中的每一個字元,當所有字元都相等時返回true,否則則返回 false。
還有一個和equals()比較類似的方法 equalsIgnoreCase(),它是用於忽略字元串的大小寫之後進行字元串對比。
3. compareTo() 比較兩個字元串
compareTo()方法用於比較兩個字元串,返回的結果為int類型的值,源碼如下:
publicintcompareTo(StringanotherString){
intlen1=value.length;
intlen2=anotherString.value.length;
//獲取到兩個字元串長度最短的那個int值intlim=Math.min(len1,len2);
charv1[]=value;
charv2[]=anotherString.value;
intk=0;
//對比每一個字元while(k<lim){
charc1=v1[k];
charc2=v2[k];
if(c1!=c2){
//有字元不相等就返回差值returnc1-c2;
}
k++;
}
returnlen1-len2;
}
從源碼中可以看出,compareTo()方法會循環對比所有的字元,當兩個字元串中有任意一個字元不相同時,則 returnchar1-char2。比如,兩個字元串分別存儲的是 1和 2,返回的值是 -1;如果存儲的是 1和 1,則返回的值是 0 ,如果存儲的是 2和 1,則返回的值是 1。
還有一個和compareTo()比較類似的方法 compareToIgnoreCase(),用於忽略大小寫後比較兩個字元串。
可以看出compareTo()方法和equals()方法都是用於比較兩個字元串的,但它們有兩點不同:
equals()可以接收一個 Object類型的參數,而 compareTo()只能接收一個String類型的參數;
equals()返回值為Boolean,而compareTo()的返回值則為int。
它們都可以用於兩個字元串的比較,當equals()方法返回true時,或者是compareTo()方法返回 0時,則表示兩個字元串完全相同。
4.其他重要方法
indexOf():查詢字元串首次出現的下標位置
lastIndexOf():查詢字元串最後出現的下標位置
contains():查詢字元串中是否包含另一個字元串
toLowerCase():把字元串全部轉換成小寫
toUpperCase():把字元串全部轉換成大寫
length():查詢字元串的長度
trim():去掉字元串首尾空格
replace():替換字元串中的某些字元
split():把字元串分割並返回字元串數組
join():把字元串數組轉為字元串
知識擴展
1.== 和equals的區別
== 對於基本數據類型來說,是用於比較 「值」是否相等的;而對於引用類型來說,是用於比較引用地址是否相同的。
查看源碼我們可以知道 Object 中也有equals() 方法,源碼如下:
publicbooleanequals(Objectobj){
return(this==obj);
}
可以看出,Object 中的 equals() 方法其實就是 ==,而 String 重寫了 equals() 方法把它修改成比較兩個字元串的值是否相等。
publicbooleanequals(ObjectanObject){
//對象引用相同直接返回trueif(this==anObject){
returntrue;
}
//判斷需要對比的值是否為String類型,如果不是則直接返回falseif(anObjectinstanceofString){
StringanotherString=(String)anObject;
intn=value.length;
if(n==anotherString.value.length){
//把兩個字元串都轉換為char數組對比charv1[]=value;
charv2[]=anotherString.value;
inti=0;
//循環比對兩個字元串的每一個字元while(n--!=0){
//如果其中有一個字元不相等就truefalse,否則繼續對比if(v1[i]!=v2[i])
returnfalse;
i++;
}
returntrue;
}
}
returnfalse;
}
2.final修飾的好處
從String類的源碼我們可以看出String是被final修飾的不可繼承類,源碼如下:
publicfinalclassString implementsjava.io.Serializable,Comparable<String>,CharSequence{//......}
那這樣設計有什麼好處呢?他會更傾向於使用 final,因為它能夠緩存結果,當你在傳參時不需要考慮誰會修改它的值;如果是可變類的話,則有可能需要重新拷貝出來一個新值進行傳參,這樣在性能上就會有一定的損失。
String 類設計成不可變的另一個原因是安全,當你在調用其他方法時,比如調用一些系統級操作指令之前,可能會有一系列校驗,如果是可變類的話,可能在你校驗過後,它的內部的值又被改變了,這樣有可能會引起嚴重的系統崩潰問題,這是迫使 String 類設計成不可變類的一個重要原因。
總結來說,使用 final 修飾的第一個好處是安全;第二個好處是高效,以 JVM 中的字元串常量池來舉例,如下兩個變數:
Strings1="java";
Strings2="java";
只有字元串是不可變時,我們才能實現字元串常量池,字元串常量池可以為我們緩存字元串,提高程序的運行效率,如下圖所示:
除此之外編譯器還會對String字元串做一些優化,例如以下代碼:
Strings1="Ja"+"va";
Strings2="Java";
System.out.println(s1==s2);
雖然s1拼接了多個字元串,但對比的結果卻是true,我們使用反編譯工具,看到的結果如下:
Compiledfrom"StringExample.java"publicclasscom.lagou.interview.StringExample{
publiccom.lagou.interview.StringExample();
Code:
0:aload_0
1:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnLineNumberTable:
line3:0publicstaticvoidmain(java.lang.String[]);
Code:
0:ldc#2//StringJava2:astore_1
3:ldc#2//StringJava5:astore_2
6:getstatic#3//Fieldjava/lang/System.out:Ljava/io/PrintStream;9:aload_1
10:aload_2
11:if_acmpne1814:iconst_1
15:goto1918:iconst_0
19:invokevirtual#4//Methodjava/io/PrintStream.println:(Z)V22:returnLineNumberTable:
line5:0line6:3line7:6line8:22}
從編譯代碼 #2 可以看出,代碼 "Ja"+"va" 被直接編譯成了 "Java" ,因此 s1==s2 的結果才是 true,這就是編譯器對字元串優化的結果。
㈥ Java中多線程,synchronized,與 AtomicInteger的問題
通過AtomicInteger來操作 是線程安全的 ,而且性能貌似遠超 用synchronized的方法
因此不用加synchronized。確實是資源的浪費。
㈦ spring源碼里的一個問題在在注冊bean的時候為什麼要在synchronized鎖定倆次
因為addSingleton方法可是在別的地方調用,如果不加同步,那麼就不會同步了。
㈧ 求:用JAVA語言編寫的銀行家演算法的源代碼
import java.util.*;
class ThreadTest {
static int type = 4, num = 10; //定義資源數目和線程數目
static int[] resource = new int[type]; //系統資源總數
//static int[] Resource = new int[type]; //副本
static Random rand = new Random();
static Bank[] bank = new Bank[num]; //線程組
Bank temp = new Bank();
public void init() {
//初始化組中每個線程,隨機填充系統資源總數
for(int i = 0; i < type; i++)
resource[i] = rand.nextInt(10) + 80;
System.out.print("Resource:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
for(int i = 0; i < bank.length; i++)
bank[i] = new Bank("#" + i);
}
public ThreadTest4() {
init();
}
class Bank extends Thread {
//銀行家演算法避免死鎖
public int[]
max = new int[type], //總共需求量
need = new int[type], //尚需資源量
allocation = new int[type]; //已分配量
private int[]
request = new int[type], //申請資源量
Resource = new int[type]; //資源副本
private boolean isFinish = false; //線程是否完成
int[][] table = new int[bank.length][type*4]; //二維資源分配表
private void init() {
// 隨機填充總共、尚需、已分配量
synchronized(resource) {
for(int i = 0; i < type; i++) {
max[i] = rand.nextInt(5) + 10;
need[i] = rand.nextInt(10);
allocation[i] = max[i] - need[i];
resource[i] -= allocation[i]; //從系統資源中減去已分配的
}
printer();
for(int i = 0; i < type; i++) {
if(resource[i] < 0) {
//若出現已分配量超出系統資源總數的錯誤則退出
System.out.println("The summation of Threads' allocations is out of range!");
System.exit(1);
}
}
}
}
public Bank(String s) {
setName(s);
init();
start();
}
public Bank() {
//none
}
public void run() {
try {
sleep(rand.nextInt(2000));
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
while(true) {
//程序沒有完成時一直不斷申請資源
if(askFor() == false) {
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
else
tryRequest();
if(noNeed() == true)
break;
}
//休眠一段時間模擬程序運行
try {
sleep(1000);
}
catch(InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(getName() + " finish!");
synchronized(resource) {
//運行結束釋放佔有資源
for(int i = 0; i < type; i++) {
resource[i] += allocation[i];
need[i] = allocation[i] = max[i] = 0;
}
}
}
private void printer() {
//列印當前資源信息
System.out.print(getName() + " Max:");
for(int i = 0; i < type; i++)
System.out.print(" " + max[i]);
System.out.print(" Allocation:");
for(int i = 0; i < type; i++)
System.out.print(" " + allocation[i]);
System.out.print(" Need:");
for(int i = 0; i < type; i++)
System.out.print(" " + need[i]);
System.out.print(" Available:");
for(int i = 0; i < type; i++)
System.out.print(" " + resource[i]);
System.out.println("");
}
private boolean askFor() {
//隨機產生申請資源量並檢測是否超標
boolean canAsk = false;
for(int i = 0; i < type; i++) {
request[i] = rand.nextInt(20);
//防止申請量超過所需量
if(request[i] > need[i])
request[i] = need[i];
}
for(int i = 0; i < type; i++) //防止隨機申請資源全為0
if(request[i] > 0)
canAsk = true;
synchronized(resource) {
//鎖住可供資源檢查是否超標
for(int i = 0; i < type; i++) {
if(request[i] > resource[i])
//如果申請資源超過可供資源則等待一段時間後重新申請
return false;
}
}
return canAsk;
}
private void tryRequest() {
//創建副本嘗試分配請求
synchronized(resource) {
for(int i = 0; i < type; i++)
//依然要防止請求量超出范圍
if(request[i] > resource[i])
return;
for(int i = 0; i < type; i++) {
//復制資源量並減去需求量到一個副本上
Resource[i] = resource[i];
Resource[i] -= request[i];
}
System.out.print(getName() + " ask for:");
for(int i = 0; i < type; i++)
System.out.print(" " + request[i]);
System.out.println("");
if(checkSafe() == true) {
//如果檢查安全則將副本值賦給資源量並修改佔有量和需求量
for(int i = 0; i < type; i++) {
resource[i] = Resource[i];
allocation[i] += request[i];
need[i] -= request[i];
}
System.out.println(getName() + " request succeed!");
}
else
System.out.println(getName() + " request fail!");
}
}
private boolean checkSafe() {
//銀行家演算法檢查安全性
synchronized(bank) {
//將線程資源信息放入二維資源分配表檢查安全性,0~type可用資源/type~type*2所需資源/type*2~type*3佔有資源/type*3~-1可用+佔用資源
for(int i = 0; i < bank.length; i++) {
for(int j = type; j < type*2; j++) {
table[i][j] = bank[i].need[j%type];
}
for(int j = type*2; j < type*3; j++) {
table[i][j] = bank[i].allocation[j%type];
}
}
//冒泡排序按需求資源從小到大排
for(int i = 0; i < bank.length; i++) {
for(int j = i; j < bank.length-1; j++) {
sort(j, 4);
}
}
//進行此時刻的安全性檢查
for(int i = 0; i < type; i++) {
table[0][i] = Resource[i];
table[0][i+type*3] = table[0][i] + table[0][i+type*2];
if(table[0][i+type*3] < table[1][i+type])
return false;
}
for(int j = 1; j < bank.length-1; j++) {
for(int k = 0; k < type; k++) {
table[j][k] = table[j-1][k+type*3];
table[j][k+type*3] = table[j][k] + table[j][k+type*2];
if(table[j][k+type*3] < table[j+1][k+type])
return false;
}
}
}
return true;
}
private void sort(int j, int k) {
//遞歸冒泡排序
int tempNum;
if(table[j][k] > table[j+1][k]) {
for(int i = type; i < type*2; i++) {
tempNum = table[j][i];
table[j][i] = table[j+1][i];
table[j+1][i] = tempNum;
}
/*temp = bank[j];
bank[j] = bank[j+1];
bank[j+1] = temp;*/
}
else if(table[j][k] == table[j+1][k] && k < type*2) //此資源量相同時遞歸下一個資源量排序並且防止超出范圍
sort(j, k+1);
}
private boolean noNeed() {
//是否還需要資源
boolean finish = true;
for(int i = 0; i < type; i++) {
if(need[i] != 0) {
finish = false;
break;
}
}
return finish;
}
}
public static void main(String[] args) {
ThreadTest t = new ThreadTest();
//後台線程,設定程序運行多長時間後自動結束
new Timeout(30000, "---Stop!!!---");
}
}