进程与线程:
进程:操作系统中的一个程序的执行周期称为一个进程
线程:一个程序同时执行多个任务。通常每一个任务称为一个线程,与进程相比,线程更“轻量级”,创建、撤销一个线程比启动一个新进程开销要小得多。没有进程就没有线程,进程一旦终止,其内的线程也将不复存在
多进程与多线程的区别:本质区别在于,每个进程都拥有自己的一套变量,而线程则共享数据。共享变量使得线程之间的通信比进程之间通信更加有效,更方便
在实际应用中,多线程体现在一个浏览器同时下载多个图片,qq收发消息同时进行
高并发:访问的线程量非常非常高
高并发带来的问题:服务器内存不够,无法处理新的请求
线程状态分为:创建、就绪、运行、阻塞、终止
java多线程的实现:创建多线程的四种方法(**********非常非常重要!!!)
1.继承Thread类实现多线程
实例:
实现多线程之后,线程的正确调用方法应该是用实例化的对象调用start()方法。
原因比较复杂,只需要简单的来理解,在java中调用多线程时Thread定义了run()方法,jvm得到运行指令后,调用本地的run(),而Thread中的run()是由JVM创建完本地操作系统级线程后回调的方法,
只需要记得在启动线程时,调用start()方法,如果调用run()方法的话,就会将run()方法当做一个普通方法调用
每一个线程对象只能启动一次,多次启动会报错,也就是说一个myThread只能调用start()一次。
run()方法里面写的是线程需要完成什么,也就是线程的逻辑
2.Runnable()接口实现多继承
实例:
Thread类的核心功能是进行线程的启动。如果一个类为了实现多线程而直接去继承Thread就会有单继承局限,所以在java中提供了Runnable接口,在Runnable接口启动时同样是调用start()方法,但是大家可以看到试讲MytareadR的对象传入到Thread实例化的对象里才能够调用start()方法,这同样和一开始说的start()的调用方式有关,在JVM底层回调run方法时,需要传入一个对象进去,但是为什么继承Thread不用呢,因为继承Thread时,默认返回的那个对象就是Thread,而实现Runnable接口时,需要把Runnable接口的对象传入进去,所以需要先传入myThreadR进入到Threa thread中。
Thread与Runnable的区别:
1.Runnable避免了单继承局限,Thread是Runnable接口的子类
2.使用Runnabe实现多继承可以更好地描述出程序共享的概念
3.代理设计模式(两个接口,一个用来实现真正的业务操作,另一个用来完成资源的调动,辅助真实业务的完成)
3.Callable实现多继承(JDK1.5以后追加的新的开发包,主要用于高并发编程)
实例:
在Callable实现多线程拥有返回值,得到返回值的方法时,使用FutureTask的对象调用get()方法
4.使用线程池进行多线程(该方法比较复杂,在最新的博客里会用单独的一个博客来写)
线程相关的操作方法:
取得线程名称:
设置线程方法:在创建线程的时候设置名称
取得当前线程对象:
设置线程优先级:
首先解释下优先级的概念,多线程是同时进行的,但是我们可以通过设置优先级的方式让指定线程大概率的优先执行,这里我说的是大概率!设置线程优先级能够使线程优先级高的大概率的优先执行,是大概率!不是肯定!这里一定要注意!
方法:
优先级:从0-10;越大越高,缺省的数值是5
join()方法:等待该线程终止,意思就是如果在主线程中调用该方法时,就会让主线程休眠,调用该方法的线程的run方法执行完毕后再开始执行主线程 使用该方法时会抛出一个异常
实例:为添加之前:
结果:
添加之后:
线程让步:yield()方法
暂停当前正在执行的线程对象,并执行其他线程
结果:
线程休眠:sleep();指的是让线程暂缓执行一下,等到了预计时间之后再恢复执行,这个方法会抛出一个异常
输出的形式是卡顿的形式输出,图片无法演示,可以自己亲自动手试一下
线程停止:
a.设置标志位,让线程正常退出 《推荐使用第一种》
b.使用stop()强制让线程停止,JDK9彻底没有了
c.使用Thread中的interrupt()中断线程 《分两种情况》
a:
结果:
C:使用interrupt()
第一种情况:线程中出现sleep、wait、join()方法,使用Thread.interr()会将线程状态设置为打断状态,根据此状态人为进行线程终止
结果:
第二种情况:线程中没有出现wait,sleep,join等方法,人为将线程停止