您的位置:首页 > 职场人生

黑马程序员——多线程(一)

2013-03-18 07:23 106 查看
------- android培训java培训、期待与您交流! ----------

一、创建线程:方式一

1、定义一个类,从Thread继承

2、重写run方法

3、创建线程对象,调用start方法

start方法启动线程,并执行run方法

(一)为什么要重写run方法呢?

Thread类是用来描述线程的,而这个线程要执行的代码就需要用一个方法来存储,就是run方法。(主线程执行的代码存放在main方法)

而Thread类本身的run方法中没有定义任何实现代码,所以只有子类重写run方法,定义自己要实现的内容,线程才有意义。

(二)run方法和start方法的区别

run方法直接被调用的时候,是被主线程执行的,和一般的对象调用方法没什么区别;

而start方法是启动一个线程,然后在新的线程中执行run方法,这时主线程继承执行后面的代码,这就是多线程了。

(三)线程的四种运行状态:

|---sleep(time)------>冻结(时间到了回到运行)

被创建----start()---->运行 |---wait()----------->冻结(notify唤醒了继续运行)

| |

stop()或 stop()

run方法执行完成 |

| |

消亡 <-----------------------

还有一个特殊的状态:临时(堵塞)状态,即具备执行资格,但没有执行权(没有分配到cpu资源)

堵塞和冻结类似,只是堵塞是被动的,而冻结是主动的(放弃执行资格)

二、创建线程:方式二

多次启动一个线程是非法的,特别是当线程已经结束执行后,不能再重新启动。

当我们需要对一个功能多次执行,并操作同一个数据时,这种方式就不能实现了。

(因为必须要创建多个线程才能多次执行这个功能,而没创建一个线程对象,对象中的数据都是自己特有的)

而用创建线程的第二种方式就可以实现:实现Runnable接口。

因为当创建多个线程时,可以把同一对象传递给线程,那么多个线程就可以同时执行对象中的run方法。

(一)创建线程:方式二:

1、定义一个类,实现Runnable接口

2、重写run方法

3、创建这个类的对象。

4、创建一个线程(Thread),并把Runnable接口的实现类的对象作为线程类的构造方法参数传递过去。

5、start启动线程。由于start方法调用的是Runnable接口的实现类的对象中的run方法,所以这个线程可以多次启动

(三) 实现方式和继承方式的区别:

1、实现方式避免了单继承的局限性,他可以在继承其他类的同时使用线程。

2、执行代码存放的位置不同,一个在Runnable接口的实现类的run方法中,一个在Thread类的子类的run方法中。

三、线程安全问题

当多条语句在操作同一线程共享数据时,在一个线程执行这些语句的空档,另一个线程有可能会进来改变共享数据,导致了共享数据的不同步。

(一)解决方案:同步

对操作同一线程共享数据的语句进行加锁,在这些语句执行完之前,不允许其他线程访问锁中的代码。

同步前提:

1、存在多个线程(对多个线程同步)

2、多个线程使用同一把锁

弊端:多个线程需要判断锁,较为消耗资源

(二)在使用多线程时,如何找出线程安全问题?

1、明确哪些代码是多线程运行代码

2、明确共享数据

3、明确多线程运行代码中哪些语句是操作共享数据的

四、同步函数

(一)同步代码块可以找一个共享对象来作为锁,而同步函数用的什么锁呢?

函数需要被对象调用,那么函数都有一个所属对象引用,就是this。

而静态同步函数在加载时没有对象,他使用的锁该函数所在类的字节码文件对象(Class对象),类名.class。

(二)静态同步函数在懒汉式单例设计模式中的应用

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;

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: