多线程学习总结 day5

来源:互联网 发布:浙江大学网络缴费平台 编辑:程序博客网 时间:2024/05/16 13:54

---------------------- android培训、java培训、期待与您交流! ---------------------- 

 每天记录一点点,进步一点点。。。

一:多线程?

进程:是一个正在执行中的程序
  每一个进程都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。

线程:就是进程中独立的空中单元
  线程控制着进程的执行
 一个进程至少有一个线程。
该进程中至少一个线程负责java程序的执行。
而且这个线程运行的代码存在于main方法中
该线程称之为主线程。

扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收的线程

1.如何在自定义的代码中,自定义一个线程呢?
通过对api的查找,java已经提供了对线程这类事物的描述,即Thread类
创建线程的第一种方式:继承Thread类
步骤:
1.定义类继承Thread

2.复写Thread 类中的run()方法
 目的:将自定义代码存储在run方法中,让线程运行。

3. 调用线程的start方法
 该方法的两个作用:启动线程,调用run()方法。 对象.start();

注意:如果Demo对象直接调用run()方法,而线程创建了,没有运行,还是主线程在运行。
  start()方法很重要,只有它才能将开启线程,而run方法仅仅是封装线程要运行的代码
  所以在Thread类在描述时,将run和start分开了


因为运行结果每一次都不同
应为多个线程获取cpu的执行权。cpu执行到谁,谁就运行,明确一点,在某一时刻
只能有一个程序在运行(多核除外),cpu 在做着快速的切换,已达到看上去是同时运行的效果
我们可以形象的把多线程的运行行为在互相强多cpu的执行权

这就是多线程的一个特性:随机性。谁抢到谁执行,至于执行多长时间,cpu说的算。


二:为什么要覆盖run方法呢?

Thread类用于描述线程。
该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法
也就是说Thread类中的run方法是用于存储线程要运行的代码。
主线程要运行的代码存放在run方法中,这是java虚拟机定义的,这也是为什么虚拟机要调用main方法的原因


三:创建线程的第二种方式?
实现Runnable接口
步骤:
1.定义类实现 Runnable接口
2.覆盖Runnable接口中的run方法
 目的:将要线程运行的代码存放在改run方法中

3.通过Thread类建立线程对象

4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
 为什么要将Runnable接口的子类对象传递给Thread的构造函数
 因为,自定义的run方法所属的对象是Runnable接口的子类对象
 所以要让线程去执行指定对象的run方法,就必须明确该run方法所属对象


5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法

实现方式和继承方式有什么区别?

实现方式的好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

两种方式的区别:
继承Thread:线程代码存放在Thread子类的run方法中
   继承好比一辆汽车在一条路上跑,每创建一个对象就要有一条路

实现Runnable:线程代码存放在接口子类的run方法中。
   实现好比多辆汽车在同一条告诉公路上跑,实现了复用,将资源独立出来了


四:多线程的安全问题?
多线程运行出现的安全问题

问题的原因:
  当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完
  另一个线程参与进来执行,导致共享数据错误

解决办法:
  对多操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行

java对于多线程的安全问题提供了专业的解决方式:
同步代码块:
synchronized(对象)
{
 需要被同步的代码...
}
对象如同锁。持有锁的线程可以再同步中执行,
没有持有锁的现场即便获取cpu执行权,也进不去,因为没有锁

同步的前提:
1.必须要有两个或者两个以上的线程。
2.必须是多个线程使用同一个锁。
必须保证同步中只有一个线程在运行。

好处:解决了多线程的安全问题
弊端:如果多个线程执行时,每次都要判断锁,较为消耗资源。

五、锁?
同步函数用的锁是this
如果同步函数被静态修饰后,使用的锁是什么呢?
通过验证,发现不是this。因为静态方法中也不一定义this
静态金内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。
类名.class 该对象的类型是Class

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

六:单例设计模式?
单例模式有两种:一种是饿汉式,另一种是懒汉式
有什么区别(面试):懒汉式的特点在于实例的延迟加载,
懒汉式延迟加载有什么问题:有,如果多线程访问时会出现安全问题,怎么解决,可以加同步来解决。
    可以加同步来解决,用同步代码块和同步函数都行,但稍微有些低效,用双重判断能解决效率问题
加同步的时候使用的锁是哪一个:该类所属的字节码文件对象。

七:线程间通讯?
其实就是多个线程在操作同一个资源,但操作的动作不同

wait()
notify()
notifyAll()

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

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

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

对于多个生产者和消费者。

为什么要定义while判断标记。
原因:让被唤醒的线程再一次判断标记

为什么定义notifyAll
因为需要唤醒对象对方线程。
如果只用notify ,容易出现只换醒本方线程的情况。导致程序的所有线程都等待


JDK1.5中提供的多线程的升级解决方案
将同步synchronized 替换成现实Lock操作
将Object中的wait(),notify(), notifyAll(),替换了Condition对象
该对象可以通过Lock锁进行获取
一个Lock锁里可以绑定多个condition对象;
而synchronized 只能绑定一个锁对象,是拿锁来区分
该示例中出现了本方只唤醒对方的操作。

面试:生产者消费者有什么替代方案?
JDK1.5版本以后提供了显示的锁机制,以及的锁对象上的等待唤醒操作机制,同时把等待唤醒进行了封装
一个锁可以对应多个condition对象,没有升级之前,一个锁只对应一个wait、notify,想再有一组wait、notify,
         需要再建一个锁,需要再建一个同步synchronized,一建锁同步,两个
         形成嵌套就容易死锁,现在一个锁可以对应几个Condition对象(好几组wait、notify)

注意:释放锁的动作一定要先执行。

八、如何停止线程?
stop方法以及过时,只有一种,run()方法结束。
开启多线程运行,运行代码通常是循环结构。
因此,只要控制住循环,就可以让run()方法结束,也就是线程结束。

特殊情况:
当线程处于了冻结状态。
就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结状态清除,强制让线程恢复到
运行状态中来,么这样就可以操作标记,让线程结束。

Thread类提供了该方法 interrupt();

Join:
当A线程执行到了B线程的join方法时,A线程就会等待,等B线程执行完,A线程才会执行

join可以用来临时加入线程执行。

先写到这吧

 ---------------------- android培训、java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买车票没有身份证怎么办 登机身份证丢了怎么办 飞机没带身份证怎么办 上飞机没带身份证怎么办 机场没带身份证怎么办 儿童坐飞机没有户口本怎么办 不需要行李托运化妆品怎么办 坐飞机被限制了怎么办 坐飞机没买保险怎么办 飞机起飞时难受怎么办 婴儿坐飞机没座位怎么办 转机行李不直达怎么办 儿童自己坐飞机怎么办手续 两岁宝宝发烧怎么办 网上购票待核验怎么办 老人坐飞机找不到登机口怎么办 儿童不能值机怎么办 飞机上旅客刁难怎么办 飞机上婴儿哭闹怎么办 飞机上婴儿啼哭怎么办 飞机儿童陪护手续怎么办 孕妇感冒鼻子堵怎么办 孕妇用了眼药水怎么办 孕妇用眼药水了怎么办 错过了登机时间怎么办 过了登机时间怎么办 孩子不喜欢做作业怎么办 宝宝腿不一样粗怎么办 一个小腿肿了怎么办 左右小腿不一样粗怎么办 小孩不敢自己睡怎么办 小孩不一个人睡怎么办 晚上一个人睡觉害怕怎么办 孩子自己睡害怕怎么办 小孩晚上睡觉怕怎么办 小孩分房睡害怕怎么办 坐飞机不认识字怎么办 科目一不识字怎么办 孩子不自己睡觉怎么办 70岁老人坐高铁怎么办 八岁儿童怎么办护照