单例设计模式。
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类中。