Java多线程第二集(多线程实现方式)

线程是cpu调度和执行的单位,每个线程拥有独立的运行栈和程序计数器(pc),线程切换的开销小。



一、线程的生命周期


· JDk中用Thread.State类定义了线程的几种状态

想要实现多线程,必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程,在他的一个完整的生命周期中通常要经历如下的五种状态:

1. 新建:当一个Thread类或其子类的对象被声明并创建时,新的线程对象处于新建状态。

2. 就绪:处于新建状态的线程被start()后,将进入线程队列等待CPU时间片,此时它已具备了运行的条件,只是没分配到CPU资源。

3. 运行:当就绪的线程被调度并获得CPU资源时,便进入运行状态,run()方法定义了线程的操作和功能。

4. 阻塞:在某种特殊情况下,被人为挂起或执行输入输出操作时,让出CPU并临时中止自己的执行,进入阻塞状态。

5. 死亡:线程完成了它的全部工作或线程被提前强制性的中止或出现异常倒置导致结束。

二、多线程实现的原理

l Java语言的JVM允许程序运行多个线程,多线程可以通过Java中的java.lang.Thread类来体现。

l Thread类的特性

1. 每个线程都是通过某个特定的Thread对象的run()方法来完成操作的,经常把run()方法的主体称为线程体。

2. 通过Thread方法的start()方法来启动这个线程,而非直接调用run()。

三、多线程创建方式

(1) 继承Thread类

1. 创建一个继承于Thread类的子类。

2. 重写Thread类的run()方法。

3. 创建Thread类的子类的对象。

4. 通过此对象调用start()来启动一个线程。


(2) 创建Thread匿名类



(3) 实现Runnable接口

1. 创建一个实现Runnable接口的类。

2. 实现类去实现Runnable接口中的抽象方法:run()。

3. 创建实现类的对象。

4. 将此对象作为参数传到Thread类的构造器中,创建Thread类的对象。

5. 通过Thread类的对象调用start()方法。



Java中只允许单进程,只能继承一个Thread类来完成多线程,但是一个类可以实现多个接口,因此实现的方式没有类的单继承性的局限性,用实现Runnable接口的方式来完成多线程更加实用。

实现Runnable接口的方式天然具有共享数据的特性(不用static变量)。因为继承Thread的实现方式,需要创建多个子类的对象来进行多线程,如果子类中有变量A,而不使用static约束变量的话,每个子类的对象都会有自己独立的变量A,只有static约束A后,子类的对象才共享变量A。而实现Runnable接口的方式,只需要创建一个实现类的对象,要将这个对象传入Thread类并创建多个Thread类的对象来完成多线程,而这多个Thread类对象实际上就是调用一个实现类对象而已。实现的方式更适合来处理多个线程有共享数据的情况。

联系:Thread类中也实现了Runnable接口

相同点两种方式都需要重写run()方法,线程的执行逻辑都在run()方法中

(4) 实现Callable接口




与Runnable相比,Callable功能更强大

1. 相比run()方法,可以有返回值

2. 方法可以抛出异常

3. 支持泛型的返回值

4. 需要借助FutureTask类,比如获取返回结果

(5) 线程池



背景

经常创建和销毁、使用量特别大的资源、比如并发情况下的线程、对性能影响很大。

思路

提前创建好多个线程,放入线程池中,使用时直接获取,使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。

优点

​ 提高响应速度(减少了创建新线程的时间)

​ 降低资源消耗(重复利用线程池中线程,不需要每次都创建)

​ 便于线程管理

四、Java调度算法

l 同优先级线程组成先进先出队列(先到先服务),使用时间片策略。

l 堆高优先级,使用优先调度的抢占式策略。

线程的优先级等级(一共有10挡)

l MAX_PRIORITY:10

l MIN_PRIORITY:1

l NORM_PRIORITY:5 (默认优先级)

获取和设置当前线程的优先级

l getPriority(); 获取

l setPriority(int p); 设置

说明:高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲,高优先级的线程高概率的情况下被执行。并不意味着只有高优先级的线程执行完成以后,低优先级的线程才执行。

五、Thread类的常用方法

l start() : 启动当前线程, 调用当前线程的run()方法

l run() : 通常需要重写Thread类中的此方法, 将创建的线程要执行的操作声明在此方法中

l currentThread() : 静态方法, 返回当前代码执行的线程

l getName() : 获取当前线程的名字

l setName() : 设置当前线程的名字

l yield() : 释放当前CPU的执行权

l join() : 在线程a中调用线程b的join(), 此时线程a进入阻塞状态, 知道线程b完全执行完以后, 线程a才结束阻塞状态

l stop() : 已过时. 当执行此方法时,强制结束当前线程.

l sleep(long militime) : 让线程睡眠指定的毫秒数,在指定时间内,线程是阻塞状态

l isAlive() :判断当前线程是否存活


六、线程的安全性上一章已经讲解。

展开阅读全文

页面更新:2024-04-23

标签:方式   子类   优先级   重写   线程   变量   接口   对象   状态   方法

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top