黑马程序员-多线程
2012-05-28 10:51
239 查看
-------------------
android培训,java培训、期待与您交流!
----------------------
多线程:
要说到线程,首先要了解什么是进程.进程就是每一个正在运行的程序,
线程就是每一个程序中的执行路径或者叫控制单元,
每一个进程都有至少一个线程, 这个线程就叫做主线程.多线程就是在一个进程中有多条执行路径.
比如迅雷,迅雷在下载的时候,可以多个下载任务同时下载,每一个下载任务就是一个线程.
如何自定义一个线程:
创建线程的第一种方式:继承Thread类
步骤:
1.
定义子类继承Thread类
2.
复写run方法,将自定义的代码存储在run方法中,让线程运行
3.
创建子类对象,调用start方法
Start方法有两个作用:1.启动线程 2.调用run方法
线程中,start和run的区别
Start:是开启线程并调用run方法
Run:存放的是线程执行的代码,如果单纯的调用run方法,只是普通的创建对象调用方法,而并没有开启线程
线程的状态:
线程有五种状态:
被创建 ; 运行 ;
冻结 ; 临时 ;
消亡
当创建Thread对象或者它的子类对象的时候,线程就被创建了
运行状态中的线程拥有执行资格和执行权,,要进入运行状态,需要从被创建状态通过start关键字运行
冻结状态中的线程没有执行资格和执行权,因为这时的线程是不动的,是停止的,冻结状态是在运行状态时通过sleep(time);或者是wait(
); 进入的如果要取消冻结状态,就需要使用notify( )方法
临时状态时的进程有执行资格,但是没有执行权,是在等待执行的进程,从冻结状态出来的进程首先应该进入临时状态等待cpu的执行
消亡状态的线程已经执行结束,或者强制结束的,强制结束通过stop( )来结束run方法.
获取线程的引用和给线程命名:
在java中,提供了一个途径来获取线程的引用(或者说线程的名字),这个方法就是
static Thread currentThread()
我们还可以给线程命名,
使用构造函数或setName给线程命名,使用getName获取线程的名字
Class Demo extends Thread
{
Demo(String name)
{
Super(name); //使用构造函数给线程命名
}
Public void run()
{
System.out.println(Demo.currentThread().getName()); //获取线程的名字,还有一个方法是this.getName()
}
}
Class show
{
public static void main(String [] ages)
{
Demo d-new Demo(“名字”); //给线程命名
d.strat(); //启动线程
}
}
实现型的多线程:
步骤:
1.
定义类,实现Runnable接口
2.
复写Runnable中的run方法
为了把线程要运行的代码放进run方法中
3.
通过Thread创建子线程对象
4.
把Runnable的子类对象作为实际参数传给Thread类的构造函数
自定义的run方法所属的对象是Runnable接口的子类对象,
所以要让线程去指定指定对象的run方法,就必须明确run方法所属的对象
5.
调用Thread的start方法开启线程并调用Runnable的子类run方法
实现方式和继承方式的区别:
因为java只支持单继承,所以如果用继承方式,那么继承了Thread类之后,这个类就不能再继承其他类了,
而使用实现方式就避免了单继承的局限性.
继承Thread:线程代码存放在Thread子类的run方法中.
实现Runnable:线程代码存放在接口实现类的run方法中
多线程出现安全问题:
问题的原因:当多个线程执行同一个线程语句的时候,可以一个线程对这个语句执行了一部分,还没有执行完,另一个线程参与了这条语句的进行,这时会导致安全问题.
解决办法:对线程执行语句的执行,只能让一个线程执行完以后,才能让其他线程参与执行
Java中对多线程安全问题提供了专业的解决办法:
同步代码块
synchronized(对象){
需要同步的代码 }
如何判断哪些代码需要同步:
只要看哪些代码操作了共享数据
同步的参数是个对象,这个对象就如同一个锁,持有锁的线程可以在同步中执行,没有持有锁的线程,就算有执行权,也不能执行,因为它没有获取锁
同步的前提:
1.
必须要有多个线程
2.
必须是多个线程使用同一个锁
同步的好处:解决了线程的安全问题
弊端:比较消耗资源
同步函数:
同步函数就是具备同步特性的函数
同步函数的格式:
访问修饰符 synchronized 返回类型函数名( ) { }
同步函数的特点:
同步函数是把整个函数一起同步了,简化了同步的代码,省略了用对象作为参数,但是如果一个函数里面有不需要同步的代码的时候,最好不要用同步函数,而要用同步代码块
如果使用同步函数,那么同步函数的锁就是this
静态同步函数的锁不是this,因为静态是随着类的出现而出现的,
当类产生的时候,还没有对象,所以也就没有this.于是静态同步函数的锁是Class的对象,
类名.class
多线程的单例设计模式(懒汉式)的特点:
懒汉式单例设计模式的特点就是延时加载,但是在多线程中,懒汉式会出现安全问题,要解决安全问题,可以使用同步函数或者同步代码块,但是使用会同步的时候,会是执行效率变慢,为了解决这个问题,可以使用多重判断的方法解决
如:
/*
*
多线程的懒汉式单例设计模式
* */
publicclass Test {
publicstaticvoid main(String[] args) {
//
TODO Auto-generated method stub
}
}
class Single {
privatestatic Single
s =
null;
private Single() {};
//私有构造函数,为了不让建立对象
publicstatic Single show() {
if (s ==
null)
//
synchronized (Single.class) {
//同步代码块,
锁是
类名.class 也就是字节码文件
if(s ==
null){
s=new Single();
//如果s==null,此时就创建对象
}
}
returns;
}
}
线程间的通信问题:
线程间的通信问题是指,多个线程操作同一个资源,但是这些线程的执行动作不一样,有的可能是出入数据,有的可能是取出数据
等待唤醒机制:
当需要一个线程进入等待状态的时候,可以使用wait,这时这个线程就进入临时状态,被存放在线程池中,此时的线程拥有执行资格但是没有执行权,想要唤醒线程池中的线程,可以使用notify(
),或者notifyAll( ).
Wait,notify( )和notifAll( )都只能使用在同步中,因为要对持有锁的线程操作,只有是同一个锁的线程才能被notify和notifyAll唤醒.
Wait,notify( )和notifAll( )在使用的时候都会抛出异常,所以在使用的时候要进行异常处理
停止线程:
当线程处于冻结状态的时候,就读不到标记了,那么线程也就不会结束,如果想让线程结束,就需要强制让线程恢复运行状态,这样就可以控制标记,使线程结束了
Interrupt()就是强制使冻结状态的线程恢复运行状态
守护线程:
守护线程可以比喻为后台线程,它依赖于前台线程的存在而存在,当前台线程全部结束的时候,守护线程也就自动结束了.
守护线程定义在启动线程之前,也就是在start()之前
使用方法:
线程名.setDaemon(true)
;
线程的优先级:
setProiority();
线程具有1-10等级的优先级,优先级越小,抢到cpu执行的能力越小
Java对三种优先级有描述1级:MIN_PRIORITY
5级:NORM_PRIORITY
10级:MAX_PRIORITY
格式:
线程名.setProiority(Thread.MAX_PRIORITY); //优先级10级
---------------------- android培训,java培训、期待与您交流!
----------------------
详细请查看http://edu.csdn.net/heima
android培训,java培训、期待与您交流!
----------------------
多线程:
要说到线程,首先要了解什么是进程.进程就是每一个正在运行的程序,线程就是每一个程序中的执行路径或者叫控制单元,
每一个进程都有至少一个线程, 这个线程就叫做主线程.多线程就是在一个进程中有多条执行路径.
比如迅雷,迅雷在下载的时候,可以多个下载任务同时下载,每一个下载任务就是一个线程.
如何自定义一个线程:
创建线程的第一种方式:继承Thread类
步骤:
1.
定义子类继承Thread类
2.
复写run方法,将自定义的代码存储在run方法中,让线程运行
3.
创建子类对象,调用start方法
Start方法有两个作用:1.启动线程 2.调用run方法
线程中,start和run的区别
Start:是开启线程并调用run方法
Run:存放的是线程执行的代码,如果单纯的调用run方法,只是普通的创建对象调用方法,而并没有开启线程
线程的状态:
线程有五种状态:
被创建 ; 运行 ;
冻结 ; 临时 ;
消亡
当创建Thread对象或者它的子类对象的时候,线程就被创建了
运行状态中的线程拥有执行资格和执行权,,要进入运行状态,需要从被创建状态通过start关键字运行
冻结状态中的线程没有执行资格和执行权,因为这时的线程是不动的,是停止的,冻结状态是在运行状态时通过sleep(time);或者是wait(
); 进入的如果要取消冻结状态,就需要使用notify( )方法
临时状态时的进程有执行资格,但是没有执行权,是在等待执行的进程,从冻结状态出来的进程首先应该进入临时状态等待cpu的执行
消亡状态的线程已经执行结束,或者强制结束的,强制结束通过stop( )来结束run方法.
获取线程的引用和给线程命名:
在java中,提供了一个途径来获取线程的引用(或者说线程的名字),这个方法就是
static Thread currentThread()
我们还可以给线程命名,
使用构造函数或setName给线程命名,使用getName获取线程的名字
Class Demo extends Thread
{
Demo(String name)
{
Super(name); //使用构造函数给线程命名
}
Public void run()
{
System.out.println(Demo.currentThread().getName()); //获取线程的名字,还有一个方法是this.getName()
}
}
Class show
{
public static void main(String [] ages)
{
Demo d-new Demo(“名字”); //给线程命名
d.strat(); //启动线程
}
}
实现型的多线程:
步骤:
1.
定义类,实现Runnable接口
2.
复写Runnable中的run方法
为了把线程要运行的代码放进run方法中
3.
通过Thread创建子线程对象
4.
把Runnable的子类对象作为实际参数传给Thread类的构造函数
自定义的run方法所属的对象是Runnable接口的子类对象,
所以要让线程去指定指定对象的run方法,就必须明确run方法所属的对象
5.
调用Thread的start方法开启线程并调用Runnable的子类run方法
实现方式和继承方式的区别:
因为java只支持单继承,所以如果用继承方式,那么继承了Thread类之后,这个类就不能再继承其他类了,
而使用实现方式就避免了单继承的局限性.
继承Thread:线程代码存放在Thread子类的run方法中.
实现Runnable:线程代码存放在接口实现类的run方法中
多线程出现安全问题:
问题的原因:当多个线程执行同一个线程语句的时候,可以一个线程对这个语句执行了一部分,还没有执行完,另一个线程参与了这条语句的进行,这时会导致安全问题.
解决办法:对线程执行语句的执行,只能让一个线程执行完以后,才能让其他线程参与执行
Java中对多线程安全问题提供了专业的解决办法:
同步代码块
synchronized(对象){
需要同步的代码 }
如何判断哪些代码需要同步:
只要看哪些代码操作了共享数据
同步的参数是个对象,这个对象就如同一个锁,持有锁的线程可以在同步中执行,没有持有锁的线程,就算有执行权,也不能执行,因为它没有获取锁
同步的前提:
1.
必须要有多个线程
2.
必须是多个线程使用同一个锁
同步的好处:解决了线程的安全问题
弊端:比较消耗资源
同步函数:
同步函数就是具备同步特性的函数
同步函数的格式:
访问修饰符 synchronized 返回类型函数名( ) { }
同步函数的特点:
同步函数是把整个函数一起同步了,简化了同步的代码,省略了用对象作为参数,但是如果一个函数里面有不需要同步的代码的时候,最好不要用同步函数,而要用同步代码块
如果使用同步函数,那么同步函数的锁就是this
静态同步函数的锁不是this,因为静态是随着类的出现而出现的,
当类产生的时候,还没有对象,所以也就没有this.于是静态同步函数的锁是Class的对象,
类名.class
多线程的单例设计模式(懒汉式)的特点:
懒汉式单例设计模式的特点就是延时加载,但是在多线程中,懒汉式会出现安全问题,要解决安全问题,可以使用同步函数或者同步代码块,但是使用会同步的时候,会是执行效率变慢,为了解决这个问题,可以使用多重判断的方法解决
如:
/*
*
多线程的懒汉式单例设计模式
* */
publicclass Test {
publicstaticvoid main(String[] args) {
//
TODO Auto-generated method stub
}
}
class Single {
privatestatic Single
s =
null;
private Single() {};
//私有构造函数,为了不让建立对象
publicstatic Single show() {
if (s ==
null)
//
synchronized (Single.class) {
//同步代码块,
锁是
类名.class 也就是字节码文件
if(s ==
null){
s=new Single();
//如果s==null,此时就创建对象
}
}
returns;
}
}
线程间的通信问题:
线程间的通信问题是指,多个线程操作同一个资源,但是这些线程的执行动作不一样,有的可能是出入数据,有的可能是取出数据
等待唤醒机制:
当需要一个线程进入等待状态的时候,可以使用wait,这时这个线程就进入临时状态,被存放在线程池中,此时的线程拥有执行资格但是没有执行权,想要唤醒线程池中的线程,可以使用notify(
),或者notifyAll( ).
Wait,notify( )和notifAll( )都只能使用在同步中,因为要对持有锁的线程操作,只有是同一个锁的线程才能被notify和notifyAll唤醒.
Wait,notify( )和notifAll( )在使用的时候都会抛出异常,所以在使用的时候要进行异常处理
停止线程:
当线程处于冻结状态的时候,就读不到标记了,那么线程也就不会结束,如果想让线程结束,就需要强制让线程恢复运行状态,这样就可以控制标记,使线程结束了
Interrupt()就是强制使冻结状态的线程恢复运行状态
守护线程:
守护线程可以比喻为后台线程,它依赖于前台线程的存在而存在,当前台线程全部结束的时候,守护线程也就自动结束了.
守护线程定义在启动线程之前,也就是在start()之前
使用方法:
线程名.setDaemon(true)
;
线程的优先级:
setProiority();
线程具有1-10等级的优先级,优先级越小,抢到cpu执行的能力越小
Java对三种优先级有描述1级:MIN_PRIORITY
5级:NORM_PRIORITY
10级:MAX_PRIORITY
格式:
线程名.setProiority(Thread.MAX_PRIORITY); //优先级10级
---------------------- android培训,java培训、期待与您交流!
----------------------
详细请查看http://edu.csdn.net/heima
相关文章推荐
- 黑马程序员--视频随笔记录--多线程1
- 黑马程序员---多线程视频之经验浅谈
- 黑马程序员--Java 多线程与并发总结
- 黑马程序员--JAVA基础复习之多线程(二)线程安全与解决方法
- 黑马程序员——java 多线程复习笔记
- 黑马程序员——多线程
- 黑马程序员——多线程
- 黑马程序员_学习日记三_多线程一
- 黑马程序员——【Java基础】——多线程
- 黑马程序员_多线程
- 黑马程序员——Java语言基础:多线程
- 黑马程序员---多线程【java】
- 黑马程序员——Java基础---多线程
- 黑马程序员——java第十一、十二天:多线程(创建线程1-2、多线程同步代码、实现Runnable接口、安全死锁)
- 黑马程序员——多线程的学习
- 黑马程序员——多线程之线程安全的实现详解
- 黑马程序员-学习日记(多线程安全问题和死锁认识)
- 黑马程序员--Java学习日记6_多线程
- 黑马程序员——多线程
- 黑马程序员JAVA基础-多线程