多线程--看谁抢得快

前言:计算机的操作系统大多采用多任务和分时设计,一个操作系统有多个独立运行的任务,每个任务对应一个进程,每个进程又可产生多个线程。

一、认识线程

1、区分进程和线程:
进程:应用程序的执行实例,有独立的内存空间和系统资源;
线程:CPU调度和分派的基本单位,执行运算的最小单位,可完成一个独立的顺序控制流程。
通俗来说就是:运行某一个软件相当于开了个进程,在这个进程中有多个工作支撑完成,这多个工作就是线程。
2、什么是多线程?
如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”;
多个线程交替占用CPU资源,而非真正的并行执行。
3、多线程的好处:
①充分利用CPU的资源;
②简化编程模型;
③带来良好的用户体验。
4、使用线程的步骤:
①、定义线程;
②、创建线程对象;
③、启动线程;
④、终止线程。

二、创建线程

每个程序至少拥有一个线程,称为主线程,main()方法是主线程的入口,我们通常编写的线程一般都是指除了主线程之外的其他线程。

一、继承Thread类创建线程

三步骤:
①、定义MyThread类继承Thread类;
②、重写run()方法,编写线程执行体 ;
③、创建线程对象,调用start()方法启动线程。
注意:创建两个对象并开始两个start(),两个线程抢占资源运行,所以每次运行结果顺序可能不一样。是否可以调用run()启动线程?
不可以!!!
原因:①只有主线程一个执行路径;②依次调用了两次run()方法。
也就是说:run()方法被当成main()中的一个普通方法执行,失去了线程的意义。
在这里插入图片描述

二、实现Runnable接口创建线程

三步骤:
①、定义MyRunnable类实现Runnable接口;
②、实现run()方法,编写线程执行体;
③、创建线程对象,调用start()方法启动线程

在这里插入图片描述
线程创建两种方式的区别
选用哪种更合适?按需选用,推荐使用实现Runnable接口。
继承Thread类
①编写简单,可直接操作线程
②适用于单继承
实现Runnable接口
①避免单继承局限性
②便于共享资源

三、线程状态

1、创建状态:创建线程对象之后,尚未调用start()之前;
2、就绪状态:调用start()方法启动线程之后;
3、运行状态:抢占到CPU资源运行的时候;
4、阻塞状态:因某种原因不能继续运行时;
5、死亡状态:一个线程run()方法运行完毕后就进入死亡状态了。

四、线程调度

一、优先级和休眠

setPriority(),只是提高抢占CPU的概率。
sleep(),线程休眠,单位毫秒,静态。
在这里插入图片描述

二、join()

用于main方法,使当前线程暂停执行,等待调用该方法的线程结束后再执行本线程。
(把子线程1join(),main方法暂停,等线程1执行完再执行main方法)

三、yield()

线程的礼让,暂停当前正在执行的线程对象,并执行其他线程;
只是提供一种可能,但是不能保证一定能实现礼让。

区分join(),yield()
yield():礼让,放手。当前线程处于就绪状态
join():阻塞当前线程,直到其他线程执行完毕,当前线程才进入就绪状态。

五、线程同步

多线程操作同一共享数据时,将引发数据不安全问题。
原因:多线程共同操作数据时,引发的冲突(如延迟时,操作未全部完成等等)
如何解决?上锁!(两种方法:同步方法和同步代码块)
①同步方法:使用synchronized修饰的方法控制对类成员变量的访问
synchronized就是为当前的线程声明一把锁。
②同步代码块:
synchronized(this){
//需要同步的代码块
}
线程同步:即各个线程之间要有个先来后到,不能一窝蜂
线程同步其实是“排队”:上锁,排队,一个一个来,不能同时操作

线程安全的类型
为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型。
在这里插入图片描述
为达到安全性和效率的平衡,可以根据实际场景来选择合适的类型。

猜你喜欢

转载自blog.csdn.net/weixin_48185778/article/details/107830763