线程是什么

       在介绍线程之前,我们就不得不想到一个词 "进程"。关于进程,我相信大家都有所了解。经常在面试的时候,面试官或多或少都会问到进程与线程的区别。

       下面,我们就来了解"进程"这个概念:

        引用百度百科上的介绍:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。大家或许不是很理解这句话,简单来说,当我们启动一个程序,例如QQ、微信、浏览器等,都会在系统中开启一个进程。下面我们通过任务管理器,能够看到当前系统所运行的进程。

       现在,我们回到上一个问题,线程和进程的区别是什么呢?线程相当于是在进程中独立运行的子任务,一个进程可以包含多个线程,多个线程可以同时运行。多线程的出现,是为了我们更加充分的利用cpu资源,如果只有一个单线程,那么系统的执行能力就会特别低下,运行效率大大降低。

言归正传,当我们了解线程的概念之后,大家想不想更加深入的了解呢?听我慢慢道来。

我们在使用之前,首先需要了解一下线程的基本状态,如果连基本状态都不清楚,以后怎么能愉快的看bug呢,大家说是吧,死锁调皮一笑(^_^)。千言万语,都比不过代码来的实在:

       在jdk1.5的时候,Thread中就定义了一个State枚举类,来定义线程的生命周期状态。注意:线程中的NEW、TERMINATEL状态不能回退。就是当线程经过NEW状态后,就不能再回到NEW状态;当线程处于TERMINATEL状态后,就不能变成其它状态。

       线程的实现方式,大致有四种实现方式:

       1.继续Thread;2.实现Runnable;3.实现Callable;4.使用线程池创建线程。

       其中1,2两种相对比较简单,Thread默认也是实现Runnable方式,由于java类只能进行单继承(接口可以多继承),资源宝贵,所以建议使用Runnable方式创建线程。另外两种,其中Callable是实现一个带返回值的线程,例如:

使用Callable方式,可以取得一个返回值,在特殊场景下,是很有用的。比如,你需要返回一个状态,来判断线程中的业务是否执行成功,就可以使用,又或者进行异步运算。还有一种,就是使用线程池技术,实现线程的创建:

jdk1.5之后,java就创建了Executors类,来方便我们创建线程,简化我们的程序,Executors中还有另外几种创建方式,这不是目 前重点,后面再详细讲解。

       现在,我们来了解一下Thead类的常用方法:

      1.与线程中断相关的三个方法:interrupt(),isInterrupted(),interrupted()。这三个方法,大家很容易就混淆了,简单的介绍一下三个方法的区别:

       interrupt(),实例方法,用来提示线程中断,设置中断标志位。这里为什么说是提示线程中断呢,因为它不会使线程立即中断,而是给线程设置了一个中断标志位,用户可以通过标志位,使线程退出。

        isInterrupted(),实例方法,通过检查中断标志位,判断线程是否被中断。不会清除中断标志位。

        interrupted(),静态方法,判断当前线程是否被中断。会清除中断标志位。

        下面我们给出一段代码来区分:

结果:

这里我们使用了interrupt(),从输出可以发现线程并没有终止,由此可以得出,线程是否终止,需要由我们自己判断。下面,我们修改一下方法:

结果:

由此,我们发现线程被终止了,并且使用isInterrupted()方法,没有清除中断标识。现在,我们把isInterrupted方法改成interrupted(),看看是什么结果:

我们发现,线程也正常结束了,但是中断标识缺变成了false,由此,可以确定interrupted()方法会清除中断标识。现在,我们已经知道这三个方法的具体区别了,希望大家能够牢记,毕竟面试的时候经常会问,别看它很简单,很容易忘记。stop()方法也可以中断线程,但是方法太过于暴力,立即结束线程运行,可能破坏数据一致性,已经被遗弃,这里就不过多描述了。

另外,当线程处于sleep()状态时,如果我们中断线程,会抛出interruptedException异常,它也会清除中断标识。

        2.join(),让调用线程在当前线程对象上进行等待。看起来,不是很好理解,我们通俗一点的讲,当一个线程需要等待另外一个线程执行结束,才开始执行,这时我们就可以使用join()方法,限于篇幅,这里我们给一段伪代码:

thread.start();

thread.join();

System.out.println("123456");

       表示当thread线程执行完成之后,再继续往下执行。join(long millis) ,方法中可以添加毫秒数,表明当线程等待时间超过给定时间,那么当前线程则会继续往下执行。

        3.sleep(),sleep(long millis)使线程沉睡,不会释放持有锁。yield(),静态方法,它会使当前线程让出CPU,但是并不是说它就不会执行了,它在让出CPU之后,会立即参与到抢夺CPU资源的队列中。

     Thread类中还有一些方法,例如Thread.setName(),Thread.setDaemon()(设置后台线程,在start()前设置,生效),Thread,setPriority()(设置线程优先级,1-10),大家可以都尝试一下,关于这些方法,平常使用不是很频繁,这里我就不做具体说明了。

       在这里,关于线程的状态,线程的创建,常用方法(Thread中的方法)做了大致的描述,希望对大家能够有所帮助。初来乍到,希望大家能够多多指正。

猜你喜欢

转载自blog.csdn.net/p_programmer/article/details/81149785