黑马程序员 -->齐头并进完成任务--多线程(上)

来源:互联网 发布:linux 网络编程 pdf 编辑:程序博客网 时间:2024/06/05 09:51

---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

进程与线程

进程:一个进程就是一个执行中的程序。每一个进程都有自己独立的一块内存空间,一组系统资源,在进程的的概念中,每一个进程的内部数据和状态都是完全独立的。

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

进程是程序的一次执行过程,是系统运行程序的基本单位。

线程:线程是进程中的一个独立的控制单元,线程在控制着进程的执行。一个进程可以拥有多个进程,但一个进程中至少要有一个线程。

线程和进程的主要差别体现在一下俩个方面:

1、 统一作为基本执行单元,线程是划分的比进程更小的执行单位。

2、 每个进程中都有一段专用的内存区域,数据存放空间是独立的,与此相反,线程月共享内存单元(包括代码和数据),通过共享的内存单元来实现数据交换,实时通讯和必要的同步操作。

 创建线程

创建线程的方法有两种:一种是继承Thread类创建线程类;另一种是实现Runnable接口创建线程类。

线程状态图


 创建线程的第一种方式:继承Thread类。

步骤:

1、定义类继承Thread类。

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

3、创建Thread子类的实例(及创建线程对象)。

4、调用线程的start方法。该方法有两个作用:启动线程,调用run方法。

代码示例:


创建线程的第二种方式:实现Runnable接口。

步骤:

1,定义类实现Runnable接口

2,覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。

3,创建Runnable实现类的实例, 通过Thread类建立线程对象。

4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。//Thread类中存在此构造方法:public Thread(Runnable target).

       //为什么要将Runnable接口的子类对象传递给Thread的构造函数?

      ( 因为,自定义的run方法所属的对象是Runnable接口的子类对象。

       所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。)

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

实现方式和继承方式的区别:

1、Runnable适合于多个相同程序代码线程去处理统一资源的情况,把虚拟的cpu(线程)同程序的代码,数据有效分离,较好体现面向对象的编程的思想。

2、Runnable可以避免由于java的单继承机制带来的局限。可以再继承其他类的同时,还能实现多线程的功能。

3、Runnable能增加程序的健壮性。代码能够被多个线程共享。

无论是继承Thread类的线程,还是实现接口runable的线程都是通过Thread类start()方法调用完成的。

这个类就像是工人,而线程就是工作。

小例子来说明一下:

class A extends Thread{}class B implements runnable{}

 A 是继承Thread 所以直接调用 start()就行

A a1 = new A() ; // 实例化对象A a2= new A() ;  // 实例化对象a1.start() ; // 调用线程主体a2.start() ; // 调用线程主体B 实现了接口 runnableB b = new B() ; // 实例化对象new Thread(b).start() ; // 调用线程主体new Thread(b).start() ; // 调用线程主体

实现方式是不很不同 A 就像一个工人一个任务;B 则是多个工人一个任务。

Runnable 代码示例:


多线程的安全问题:

视频中毕老师为了让程序出现安全问题,因此调用了Thread类中的静态方法sleep()方法。

sleep()方法介绍 Thread.sleep(longmillis)    

sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非 

(1)醒来的线程具有更高的优先级。   

(2)正在运行的线程因为其它原因而阻塞。 

调用方法:

try{thread.sleep(10);}catch{Exception e}

多线程出现安全问题的原因:

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

解决的办法:

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

Java对多线程的安全问题提供了专业的解决方法,就是同步。

同步代码块:

Synchronized(对象){     需要被同步的代码}

同步的前提:

1、  必须要有俩个或者俩个以上的线程。

2、 必须是多个线程使用同一个锁。

3、 必须保证同步中只能有一个线程在运行。

同步函数

修饰符synchronized放在返回类型的前面,定义在函数上:public synchronsized void show()对象是this。

如果出现安全问题,如何找问题:

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

2、明确共享数据

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

静态的同步函数,如果同步函数被静态修饰后,使用的锁就不再是this了,因为在静态方法中不可以定义this。所以静态方法使用的锁是该方法所在类的字节码文件对象,(对象.class )


---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------