A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

第十一天:多线程
1进程与线程(FlashGet)
    进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一        个控制单元。
   线程:就是进程中的一个独立的控制单元。线程在控制进程的执行。
一个进程中至少有一个线程。
Java VM 启动的时候会有一个进程java.exe
该进程至少一个线程负责java程序的执行。而且这个线程运行的代码会存在于main方法中,该线程称之为主线程。
拓展:其实更细节说明jvm,jvm启动不止一个线程,还有垃圾回收机制的线程。

2如何在自定义的代码中,自定义一个线程?
通过对api的查找,java已经提供了对线程这类事物的描述。就是Thread类。
创建线程的第一种方式,继承Thread类,覆盖run()方法
建立好一个对象就创建好一个线程。

步骤:
1.定义一个类继承Thread类
2.覆盖Thread类的run()方法
3.调用现成的start方法
该方法两个作用:启动线层,调用run方法
Cpu每次只是在执行一个程序,只是在快速的不同线程间进行切换。多线程的运行行为就是在互相抢夺cpu的执行权。这就是多线程的一个特性:随机性。

3为什么要覆盖run方法?
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run()方法。run()用于存储线程要运行的代码
目的是将自定义的代码存储在run()方法中,让线程运行
例一:
  1. class Demo extends Thread
  2. {
  3.         public void run()
  4.         {
  5.                 for(int x=0; x<60; x++)
  6.                         System.out.println("demo run----"+x);
  7.         }
  8. }

  9. class ThreadDemo
  10. {
  11.         public static void main(String[] args)
  12.         {
  13.                 //for(int x=0; x<4000; x++)
  14.                 //System.out.println("Hello World!");

  15.                 Demo d = new Demo();//创建好一个线程。
  16.                 //d.start();//开启线程并执行该线程的run方法。
  17.                 d.run();//仅仅是对象调用方法。而线程创建了,并没有运行。

  18.                 for(int x=0; x<60; x++)
  19.                         System.out.println("Hello World!--"+x);       
  20.         }
  21. }
复制代码

4线程运行状态
被创建:start()
运行:具备执行资格,同时具备执行权
冻结:sleep(time):时间到就结束sleep状态。wait()—notify()唤醒;线程释放了执行权,同时释放了执行资格;
临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;
消亡:stop() run方法结束

5获取线程的名称和对象
        线程都拥有自己的默认的名称。Thread-编号,该编号从0开始。
获取线程名称的方法:Thread.currentThread().geiName()

getName():获取线程的名称
Static Thread currentThread():获取当前线程的对象

设置线程名称:setName或者构造函数传参

6多线程创建的方式2
实现runnable 接口
步骤:
1.定义类实现runnable接口
2.覆盖runnable接口的run方法
将线程要运行的代码存放在该run方法中
3.通过Thread类建立线程对象
4.将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数
自定义的run方法所述的对象是Runnable接口的子类对象
所以要让线程去指定指定对象的run方法,就必须明确该run方法所属对象
5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法

两种方式的区别:
继承Thread :线程代码存放在Thread子类中的run方法中。
实现Runnable:线程代码存放在接口的子类run方法中

6多线程安全
安全问题产生的原因:多条语句在操作同一个共享数据的时候,一个线程对多条语句只执行了一部分,还没有执行完,另一份线程参与进来执行。导致共享数据的错误。
解决办法:对多条操作空想数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行
方式:同步代码块
Synchronized(对象)
{
需要被同步的代码(共享数据)
}

对象如同锁,持有锁的线程可以再同步中执行,没有锁的线程,即使获得了cpu的执行权,也进不去,因为没有获取锁。

同步的前提:
1.必须要有两个或者两个以上的线程
2.必须多个线程必须使用同一个锁。

必须保证同步中只能有一个线程在运行
同步的好处:
解决了线程的安全问题
弊端:消耗了资源,多个线程需要判断锁

7同步函数
如何找出多线程问题:
1.明确哪些代码是多线程运行代码
2.明确共享数据
3.明确多线程运行代码中哪些语句是操作共享数据的

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

如果同步函数被静态修饰后,使用得锁是类名.class
静态进内存时,内存中没有本类对象,但是一定有该类对应的字节码文件对象。

8死锁
同步中嵌套同步,可能会发生。
由于两个线程相互等待对方已被锁定的资源

避免死锁的一个通用经验法则是:当几个线程都要访问共享资源A,B,C时
保证每个线程都按照同样的顺序去访问他们,比如都先访问A,再访问B和C

3 个回复

倒序浏览
第十一天都学到这了?
回复 使用道具 举报
Hison_lian 发表于 2015-5-19 21:07
第十一天都学到这了?

毕老师的视频啊
回复 使用道具 举报
学的很快嘛   
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马