單例設計模式。
1、餓漢式
/*
class Single{
//寫上final更嚴謹,s永遠指向Single()
private static [final] Single s=new
Single();
private Single(){}
public static Single getInstance(){
return s;
}
}
*/
***********************
************************
************************
2、懶漢式*****面試****
//在多線程訪問時,會產生安全隱患
1.懶漢式與餓漢式有什麼不同?
懶漢式的特點:用於執行個體的延時載入
2.執行個體的延時載入有沒有問題?
有。如果多線程訪問時,會出現安全問題。
3.怎麼解決?
可以使用同步來解決。而加同步的方式,用同步函
數或者同步代碼塊都行,但是稍微有些低效。
4.怎麼解決低效?
用雙重判斷的形式來解決低效問題。
5.加同步的時候,使用的鎖是哪一個?
該類所屬的位元組碼物件導向。
6.筆試題:寫出一個延時載入的單例設計模式執行個體
。(如下)
class Single{
private static Single s=null;
private Single(){}
public static [synchronized] Single
getInstance(){
if(s==null){
synchronized(Single.class){
if(s==null){
//--> Thread A
s=new Single();
}
}
}
return s;
}
}
死結。
就是說,A持有一個鎖,B也持有一個鎖,A要到B裡
面去運行,要拿B的鎖,而B要到A裡面運行,必須
拿A的鎖,這樣會出現,A不放自己的鎖,去B裡面
運行,B也不放自己的鎖,到A裡面去運行,誰都不
放,就導致死結。這樣出現的情況是:程式就不會
運行了。
最可能出現死結的是:同步中嵌套同步,而鎖不同
。
************面試******
請寫一個死結的程式?
死結例子:
class Test implements Runnable
{
private boolean flag;
Test(boolean flag){
this.flag=flag;
}
public void run(){
if(flag){
while(true){
synchronized
(MyLock.locka){
syso("if TestA")
synchronized
(MyLock.lockb){
syso("else testB");
}
}
}
}else {
while(true){
synchronized
(MyLock.lockb){
syso("if TestB");
synchronized
(MyLock.locka){
syso("else testA");
}
}
}
}
}
}
class MyLock
{
static Object locka=new Object();
static Object lockb=new Object();
}
class DeadLockTest{
public static void main(String []
args){
Thread t1=new Thread(new Test(true));
Thread t2=new Thread(new Test(flase));
t1.start();
t2.start();
}
}
多線程間的通訊
常式
---input-->資源---output--->
思考1:
wait(),notify(),notifyAll(),用來操作線程為什
麼定義在Object類中?
1、這些方法存在與同步中。
2、使用這些方法時必須要標識所屬的同步鎖。
3、鎖可以是任意對象,所以任意對象調用的方法
一定定義Object類中。
思考2:
wait(),sleep()有什麼區別?
wait():釋放資源,釋放鎖。
sleep():釋放資源,不釋放鎖。
線程間通訊:
其實就是多個線程在操作同一個資源。但是操作的
動作不同。
class Res{
String name;
String sex;
}
class Input implements Runnable
{
private Res r;
//Object obj=new Object();
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true)
{
//資源是唯一的所以就傳r
synchronized(r){
if(x==0){
r.name="mike";
r.sex="man"
}else{
r.name="XX";
r.sex="X"
}
x=(x+1)%2;
}
}
}
}
class Output implements Runnable
{
private Res r;
//Object obj=new Object();
Onput(Res r){
this.r=r;
}
public void run(){
while(true)
{
synchronized(r){
syso(r.name+r.sex);
}
}
}
}
class InputOutputDemo
{
public static void main(String []
args)
{
Res r=new Res();
Input in=new Input(r);
Output out=new Output(r);
Thread t1=new Thread(in);
Thread t2=new Thread(out);
t1.start();
t2.start();
}
}
****線程間通訊--------等待喚醒機制
例題:
class Res{
String name;
String sex;
boolean flag=false;
}
class Input implements Runnable
{
private Res r;
//Object obj=new Object();
Input(Res r){
this.r=r;
}
public void run(){
int x=0;
while(true)
{
//資源是唯一的所以就傳r
synchronized(r){
if(r.flag)
try{r.wait();}catch(){}//放棄了執行
資格
//放在線上程池裡
if(x==0){
r.name="mike";
r.sex="man"
}else{
r.name="XX";
r.sex="X"
}
x=(x+1)%2;
r.flag=true;
r.notify();
//喚醒線程池裡線程,通常喚醒第一個被喚醒的
}
}
}
}
class Output implements Runnable
{
private Res r;
//Object obj=new Object();
Onput(Res r){
this.r=r;
}
public void run(){
while(true)
{
synchronized(r){
if(!r.flay)
try{r.wait();}catch(){}
syso(r.name+r.sex);
r.flag=false;
r.notify();
}
}
}
}
class InputOutputDemo
{
public static void main(String []
args)
{
Res r=new Res();
Input in=new Input(r);
Output out=new Output(r);
Thread t1=new Thread(in);
Thread t2=new Thread(out);
t1.start();
t2.start();
}
}
------------------------------
wait():
notify():
notifyAll():
都使用在同步中,因為要對持有監視器(鎖)的線
程操作。
所以要使用在同步中,因為只有同步才具有鎖。
為什麼這些操作線程的方法要定義在Object類中呢
?
因為這些方法在操作同步中線程時,都必須要標識
他們所操作線程只有的鎖,只有同一個鎖上的被等
待線程,可以被同一個鎖上notify喚醒。
不可以對不同鎖中的線程進行喚醒。
也就是說,等待和喚醒必須是同一個鎖。
而鎖可以是任意對象,所以可以被任意對象調用的
方法定義在Object類中。