黑马程序员——多线程

来源:互联网 发布:开心保健康保 知乎 编辑:程序博客网 时间:2024/06/13 22:58
------<a target=_blank href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------



多线程

一、进程与线程

进程:正在进行中的程序。 

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

进程负责的是应用程序的空间的标示。线程负责的是应用程序的执行顺序。



一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线 程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区、自己的变量。

jvm 在启动的时,首先有一个主线程,负责程序的执行,调用的是 main 函数。主线程执行的代码都在 main 方法中。 当产生垃圾时,收垃圾的动作,是不需要主线程来完成,因为这样,会出现主线程中的代码执行会停止,会去运行垃圾回收器代码,效率较低,所以由单独一个线程来负责垃圾回收。



随机性的原理:因为 cpu 的快速切换造成,哪个线程获取到了 cpu 的执行权,哪个线程就 执行。

线程的名称是由:Thread-编号定义的。编号从 0 开始。 线程要运行的代码都统一存放在了 run 方法中。线程要运行必须要通过类中指定的方法开启。start 方法。(启动后,就多了一条执行路径)



二、创建线程的方式

第一种方式:继承 Thread ,由子类复写 run 方法。


步骤:

1,定义类继承 Thread 类;


2,复写Thread 类中的 run 方法,将要让线程运行的代码都存储到 run 方法中;


3,通过创建 Thread 类的子类对象,创建线程对象;


4,调用线程的 start 方法,开启线程,并执行 run 方法。





线程状态:


被创建:start()


运行:具备执行资格,同时具备执行权;


冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;


临时阻塞状态:线程具备 cpu 的执行资格,没有 cpu 的执行权;


消亡:stop()



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


步骤:


1,定义类实现 Runnable 接口。


2,覆盖接口中的 run 方法(用于封装线程要运行的代码)。


3,通过 Thread 类创建线程对象;


4,将实现了 Runnable 接口的子类对象作为实际参数传递给 Thread 类中的构造函数。 为什么要传递呢?因为要让线程对象明确要运行的 run 方法所属的对象。


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



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

实现方式避免了单继承的局限性。定义线程建议使用实现方式。


三、等待唤醒机制(线程间的通信)

wait:将同步中的线程处于冻结状态。释放了执行权,释放了资格。同时将线程对象存储到线程池中。

notify:唤醒线程池中某一个等待线程。 

notifyAll:唤醒的是线程池中的所有线程。



注意: 

1:这些方法都需要定义在同步中。


2:因为这些方法必须要标示所属的锁。你要知道 A 锁上的线程被 wait 了,那这个线程就相当于处于 A 锁的线程池中,只能 A锁的 notify 唤醒。


3:这三个方法都定义在 Object 类中。为什么操作线程的方法定义在 Object 类中? 因为这三个方法都需要定义同步内,并标示所属的同步锁,既然被锁调用,而锁又可以是任意对象,那么能被任意对象调用的方法一定定义在 Object 类中。 


wait 和 sleep 区别: 

分析这两个方法:从执行权和锁上来分析:


wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的 notify 或者 notifyAll 来唤醒。

sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。

wait:线程会释放执行权,而且线程会释放锁。 

Sleep:线程会释放执行权,但不是不释放锁。



四、线程的停止

通过 stop 方法就可以停止线程。但是这个方式过时了。 

停止线程:原理就是:让线程运行的代码结束,也就是结束 run 方法。

怎么结束 run 方法?一般 run 方法里肯定定义循环。所以只要结束循环即可。 


第一种方式:定义循环的结束标记。

第二种方式:如果线程处于了冻结状态,是不可能读到标记的,这时就需要通过 Thread 类中的 interrupt 方法,将其冻结状态强制清除。让线程恢复具备执行资格的状态,让线程可以读到标记,并结束。


---------< java.lang.Thread >----------


interrupt():中断线程。


setPriority(int newPriority):更改线程的优先级。 

getPriority():返回线程的优先级。 

toString():返回该线程的字符串表示形式,包括线程名称、优先级和线程组。 

Thread.yield():暂停当前正在执行的线程对象,并执行其他线程。 

setDaemon(true):将该线程标记为守护线程或用户线程。将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。

join:临时加入一个线程的时候可以使用 join 方法。当A线程遇到B线程join后,A线程会等待B线程执行完后,才继续执行。




0 0
原创粉丝点击