当老师讲到多线程安全时我就想到上火车厕所的例子,最后老师也提到...



毕老师将了个买票的例子,主要是介绍创建线程的第二种方式:实现Runable接口。
相对于Thread继承方法来说,能实现的功能多了且能解决有其他继承冲突问题。
个人觉得Thread继承方法只不过讲多线程的原理。实际用的情况实现Runable接口方法完全
代替Thread。
当讲到java对于多线程的安全问题提供了专业的解决方式就是同步代码块。
synchronnized(对象)时,我就想这个用上厕所的例子最合适,刚想到这毕老师就讲了个
上火车厕所的例子 O(∩_∩)O哈哈~跟我想的一样。

同步函数有两种表现形式  一、同步代码块 二、同步函数
同步函数用的锁是this。如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不是this。因为静态方法中也不可以定义this。

静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class  该对象的类型是Class

静态的同步方法,使用的锁是该方法所在类的字节码文件对象,也就是 类名.class

死琐。
同步中嵌套同步,

多线程  
1,如何在自定义代码中,定义一个线程呢?

通过API的查找,java已经提供了对线程这类事物的描述。就Thread类。

创建线程的第一种方式:集成Thread类
步骤:
1,定义类继承Thread.
2,复写Thread类种的run方法。
3,调用线程的start方法,该方法有两个作用启动线程 调用run方法。


我们可以形象的把多线程的运行行为在互相抢夺者cpu的执行权。
这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长时间,cpu说了算。 

class Demo extends Thread
{
public void run()
{
System.out.println("demo run");
}
}


class ThreadDemo
{
public static void main(String[] args)
{
 Demo d = new Demo();
d.start();
}
}


static Thread currentThread():获取当前线程对象。
getName():获取线程的名称。
设置线程名称:setName();


创建线程的第二种方式:实现Runable接口


步骤
1,定义类实现Runnable接口
2,覆盖runnable接口的run方法。
3,通过runnable类建立线程对象。
4,将runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
为什么要将runnable接口的子类对象传递给Thread的构造函数。
因为,自定义的run方法所属的对象时runnable接口的子类对象。
所以要线程去指定对象的run方法。就必须明确该run方法所属对象。


实现方式和集成方式有什么区别呢?
实现方式的好处:避免了单继承的局限性。
在定义线程时,建议使用实现方式。


两种方式区别;
集成Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存放在接口的子类的run方法。
5,调用Thread类的start方法开启线程并调用runnable接口子类的run方法。

多窗口买票的列子


class Ticket implements Runnable //extends Thread
{
private static int tick = 100;
Object obj = new Object();
public void run()
{
while(true)
{
synchronized(obj)//同步解决了安全问题,执行速度会变慢
{
if(tick>0)
{
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"sale:"+tick--);
}
}
}

}
}




class TicketDemo
{
public static void main(String[] args)
{
/*
Ticket t1 = new Ticket();
Ticket t2 = new Ticket();
Ticket t3 = new Ticket();
Ticket t4 = new Ticket();
*/
Ticket t = new Ticket();

Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
Thread t3 = new Thread(t);
Thread t4 = new Thread(t);

t1.start();
t2.start();
t3.start();
t4.start();
}
}




单例设计模式中多线程遇见的问题。


//饿函数


class Single
{
private static final Single s = new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}




//懒汉式  多线程的时候会出现安全问题 怎么解决


class Single
{
private static Single s = null;
private Single(){}


public static Single getInstance()
{
if(s ==null)
{
synchronized(Single.class)
{
if(s==null)
s=new Single();
}
}
return s;

}


多线程 同步 等待唤醒机制。
wait:
notify();
notifyAll();


都使用在同步中,因为要对持有监视器(锁)的线程操作。
所以要使用在同步中,因为只有同步才具有锁。


为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标示他们所操作线程只有的锁。
只有同一个锁上的被等待方法,可以被同一个锁上的notify唤醒。
不可以对不同锁中的线程进行唤醒。


也就是说,等待和唤醒必须是同一个锁。
而锁可以是任意对象,可以被任意对象调用的方法定义Object类中。


你可能感兴趣的:(当老师讲到多线程安全时我就想到上火车厕所的例子,最后老师也提到...)