java 汇总_java基础汇总
1.關于Http和Hibernatet里面Session的區別
HttpSession
HttpSession:是一個抽象接口,J2EE的Web程序在運行的時候,會給每一個新的訪問者建立一個HttpSession,這個Session是用戶身份的唯一標示,WEB?會話跟蹤用的?!咀?是容器(Tomca)自動創建的】
HttpSession用途:存放用戶的一些經常被用到的信息,如:用戶名,權限。
HttpSession獲取方法:HttpSession session = request.getSession();
Hibernate?Session
Hibernate?Session是把JDBC的Connection和Transaction接口進行了簡單的封裝后的一個接口,即此Session主要用來管理對象的增、刪、改、查和事務的,還有只要持久化類的實例對象與Session關聯了,那此對象就不只是簡單的在內存中了,而是可以通過Session對象去管理它了,所以也稱此對象在Session緩存中即Hibernate所提到的一級緩存。
2.使用Boolean類型同步鎖引起異常的分析
public class MyTest {
public static void main(String[] args) throws Exception {
new TestThread().start();
new TestThread().start();
Thread.sleep(1000);
System.out.println("Doing something...");
synchronized (lock) {
lock = false; // 語句1
lock.notifyAll(); // 語句2
}
}
static volatile Boolean lock = true;
}
class TestThread extends Thread {
@Override
public void run() {
synchronized (MyTest.lock) {
while (MyTest.lock) {
try {
MyTest.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getId());
}
}
}
輸出結果為
Doing something...
Exception in thread
"
main
"
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at MyTest.test(MyTest.java:
13
)
at MyTest.main(MyTest.java:
3
如果
把語句1和語句2調換一下就正常了。 大家給診斷一下,到底是為什么?
討論過程請大家自行參考原始的帖子和我的整理帖子,這里只給出最終的分析結果
分析:
當作為同步鎖的對象發生改變時,比如換了一個新的對象,那么如果在新的對象上調用同步的wait等方法,由于并沒有同步這個對象,而是同步的改變以前的那個,就會報出如上的異常。 我們來看代碼
synchronized (lock) {
lock = false; // 語句1
lock.notifyAll(); // 語句2
}
語句1那里修改了lock的對象指向,結果造成下面的一句notifyAll使用了一個并沒有synchronized的對象,隨意報出了異常。
解決方法
方案1,使用Boolean的特殊性?由于 lock=false;的特殊性,分析Boolean的源代碼發現
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
//發現其內部對于自動打包,拆包只使用了2個固定的對象。所以可以用
synchronized (lock) {
lock = false; // 語句1
Boolean.TRUE.notifyAll(); // 語句2
}
// 直接使用那個TRUE就行了。
方法2:使用一個參數可變對象,而不是不可變的,
比如
class MyLock {
boolean lock = true;
}
static volatile MyLock lock = new MyLock();
// 然后再代碼里面用
lock.lock=false;// 進行標志的變更和判斷就可以了
結論:
同步鎖最好單獨使用,如果鎖自身附帶了其它作用,應使用一個可變的對象 推薦
static volatile MyLock lock = new MyLock();
應該寫成:
final static volatile MyLock lock = new MyLock();
注意:volatile修飾符
Volatile修飾的成員變量在每次被線程訪問時,都強迫從共享內存中重讀該成員變量的值。而且,當成員變量發生變化時,強迫線程將變化值回寫到共享內存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。
Java語言規范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變量的原始值對比。
這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變量的變化。
而volatile關鍵字就是提示VM:對于這個成員變量不能保存它的私有拷貝,而應直接與共享成員變量交互。
使用建議:在兩個或者更多的線程訪問的成員變量上使用volatile。當要訪問的變量已在synchronized代碼塊中,或者為常量時,不必使用。 由于使用volatile屏蔽掉了VM中必要的代碼優化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。
3.死鎖和活鎖
一、活鎖
如果事務T1封鎖了數據R,事務T2又請求封鎖R,于是T2等待。T3也請求封鎖R,當T1釋放了R上的封鎖之后系統首先批準了T3的請求,T2仍然等待。然后T4又請求封鎖R,當T3釋放了R上的封鎖之后系統又批準了T4的請求,...,T2有可能永遠等待,這就是活鎖的情形,如圖8.4(a)所示。
避免活鎖的簡單方法是采用先來先服務的策略。
二、死鎖 如果事務T1封鎖了數據R1,T2封鎖了數據R2,然后T1又請求封鎖R2,因T2已封鎖了R2,于是T1等待T2釋放R2上的鎖。接著T2又申請封鎖R1,因T1已封鎖了R1,T2也只能等待T1釋放R1上的鎖。這樣就出現了T1在等待T2,而T2又在等待T1的局面,T1和T2兩個事務永遠不能結束,形成死鎖。
總結
以上是生活随笔為你收集整理的java 汇总_java基础汇总的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux内核实现ipsec,IP XF
- 下一篇: SpringBoot项目的 pom.x