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

黑马程序员——多线程

2014-01-09 14:15 106 查看
 ------- android培训java培训、期待与您交流!
----------

线程的定义

进程:当前正在执行的程序,代表一个应用程序在内存中的执行区域。

线程:是进程中的一个执行控制单元,执行路径。

一个进程中如果只有一个执行路径,这个程序称为单线程。

一个进程中有多个执行路径时,这个程序成为多线程。

多线程的好处:它的出现可以同时执行多条路径,让多部分代码同时执行,提高了效率

jvm启动不止一个线程,除了主线程,还有负责垃圾回收机制打的线程

 

 

创建线程

 1,继承Thread

  定义类继承Thread

  重写run方法(Thread类中的run方法用于存储线程要运行的代码)

  把新线程要做的事写在run方法中

  创建线程对象

  开启新线程,调用start()方法,程序内部会自动执行run方法

 

Thread类常用方法

 1,设置名字

  通过构造函数可以传入String类型的名字super(String);

  通过setName(String)方法可以设置线程对象的名字

 2,获取名字

  通过getName()方法获取线程对象的名字

 3,获取当前线程对象

  Thread.currentThread(),主线程也可以获取

 4,休眠

  Thread.sleep(毫秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒 

 5,守护

  setDaemon(),该方法在启动前调用。设置一个线程为守护线程,该线程不会单独执行,当其他非守护线程都执行结束后,自动退出

 6,加入

  join(), 主线程暂停, 等待使用join方法的线程执行结束后,主线程再继续

  join(int), 可以等待指定的毫秒之后继续

 7,yield停止当前线程,运行其他线程

 

2,实现Runnable

  定义类实现Runnable接口

  创建run方法

  把新线程要运行的代码存放在run方法中

  创建自定义的Runnable对象

  创建Thread对象,传入Runnable接口的子类对象

  调用start()开启新线程, 内部会自动调用Runnable的run()方法

 

 

两种方式的区别

  区别一:

  由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法

  构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable是否为空, 不为空则执行Runnable的run()

  区别二:

  继承Thread只能是单继承,如果自己定义的线程类已经有了父类,就不能再继承了

  实现Runnable接口可以多实现,即使自己定义线程类已经有父类可以实现Runnable接口

 

 

继承Thread的好处是:可以直接使用Thread类中的方法,代码简单

                         弊端是:如果已经有了父类,就不能用这种方法

 实现Runnable接口的好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口。而且接口是可以多实现的

                             弊端是:不能直接使用Thread中的方法。需要先获取到线程对象后,才能得到Thread的方法,代码复杂

wait()和sleep()有什么区别?

对时间的指定。

1,sleep方法必须指定时间。

2,wait方法有重载形式,可以指定时间,也可以不指定时间。

对于执行权和锁的操作.

1,sleep():释放执行权,不释放锁,因为肯定能醒,肯定可以恢复到临时阻塞状态。

2,wait():释放执行权,释放锁。

 

 

线程之间的同步

当多线程并发,有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作,这时就需要同步

如果两段代码是同步的,那么同一时间只能执行一段,在一段代码没执行结束之前,不会执行另外一段代码。

 

同步代码块

格式:

synchronized(对象)

{//该对象可以是任意对象

 需要同步的代码;

}

同步中执行同步可以解决安全问题的根本原因就在那个对象上,对象如同锁的功能,持有锁的线程可以执行(例子:火车卫生间)

 

 同步的特点:

同步的前提:

同步需要两个或者两个以上的线程。

多个线程使用的是同一个锁。

未满足这两个条件,不能称其为同步。

同步的好处:

同步的出现解决了多线程的安全问题。

同步的弊端:

当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率

 

同步函数

  使用synchronized关键字修饰一个方法。该函数中所有的代码都是同步的

  非静态同步方法默认使用当前对象this作为锁对象

 

静态同步函数的锁

静态函数使用的锁肯定不是this,因为静态函数中不可以定义this

静态随着类的加载而加载,这时有可能内容还没有该类的对象,但是一个类加载进内存,会先将这个类对应的字节码文件封装成对象,该对象的表示方式:类名.class

 

 

线程之间的通信

 

  如果希望线程等待,就调用wait()

  如果希望唤醒等待的线程,就调用notify();

  这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用

多个线程通信的问题

  notify()方法是随机唤醒一个线程(优先唤醒先等待的线程)

  notifyAll()方法是唤醒所有线程

 

JDK1.5之前无法唤醒指定的一个线程

  如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件

 

1.5中提供了多线程升级解决方案:

将同步Synchronized替换成现实Lock操作,

将object中wait,notify,notifyAll替换成了Condition对象

该对象可以通过Lock锁进行获取  lock.newCondition()

 

停止线程:

run方法结束,只有控制循环,就可以让run方法结束。

 

特殊情况:

当线程处于冻结状态,就不会读取到标记,线程不会结束。

当没有指定的方发让冻结的线程恢复到运行状态时,这时需要对冻结进行清除

强制让线程恢复到运行状态中,这样就可以操作标记让线程结束

Thread类提供该方法 interrupt()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: