随着开发项目中业务功能的增加,必然某些功能会涉及到线程以及并发编程的知识点。笔者就在现在的公司接触到了很多软硬件结合和socket通讯的项目了,很多的功能运用到了串口通讯编程,串口通讯编程的安卓端就是基于线程的方式和硬件保持通讯的。
关于Java线程,先了解一下Java线程的生命周期和物种基本状态,先上一张经典的图
上图也比较直观的绘制了关于Java线程的生命周期同时也囊括了Java线程的重点知识点。
heading" data-id="heading-0">Java线程的五种状态:
heading" data-id="heading-1">新建状态(New):
当线程对象创建后,线程即进入新建状态,如:Thread t = new MyThread();
heading" data-id="heading-2">就绪状态(Runnable):
当线程对象的start()方法(t.start();)调用时,此时线程进入就绪状态。处于就绪状态的线程只能说明线程此时已经做好准备,随时等待cpu的调度并不是说 t.start(): 后线程就会立马执行;
heading" data-id="heading-3">运行状态(Running):
当cpu开始调度已经处于就绪状态的线程时,此时线程才真正的开始他的工作,即进入了运行状态。注意(敲黑板!):就绪状态是进入到运行状态的唯一入口。也就是说线程想进入运行状态,那线程就必须先处于就绪状态。
heading" data-id="heading-4">阻塞状态(Blocked):
处于运行状态的线程处于某种原因呢,暂时放弃了对cpu的使用权,停止了执行,此时也就进入了阻塞状态,知道线程再次进入到就绪状态,才有机会被cpu调用进入到运行状态。而根据造成阻塞的原因不同,分为了一下三种阻塞:
-
等待阻塞:运行状态的线程执行到了wate()方法,使线程进入了等待阻塞状态。
-
同步阻塞:线程在获取synchronized同步锁失败(因为锁被其他线程占用),他就会进入同步阻塞状态。
-
其他阻塞:通过线程的sleep()和join()或发出了I/O请求,线程进入到了阻塞状态。当sleep()超时、join()等待线程终止或超时、I/O处理完毕时,线程就会再次进入就绪状态。
heading" data-id="heading-5">死亡状态(Dead):
线程执行完了或者在执行中因异常退出了run()方法,该线程就走完了他的一生了。
heading" data-id="heading-6">Java多线程的创建和启动
Java线程有三种常见的基本创建方式
heading" data-id="heading-7">继承Thread类,重写其run()方法
heading" data-id="heading-8">实现Runnable接口,并重写实现其run()方法
不必想太多,这个run()方法同样是我们的线程执行体。重写完run方法后创建接口实例,并把该实例作为创建线程的target创建线程。没看懂没关系,直接上代码。
heading" data-id="heading-9">用Callable和Future接口创建线程
具体是创建Callable接口的实现类,并实现call()方法。并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建线程。有点绕~直接看代码吧~
这样我们就能清楚的看得出他们之间的关系。发现FutureTask类实际上是同时实现了Runnable和Future接口,使得他有了双重特性了,通过Runnable特性,可以作为Thread对象的target,而Future特性,使得其可以取得新创建线程中的call()方法的返回值。
原因在于通过ft.get()方法获取子线程call()方法的返回值时,当子线程此方法还未执行完毕,ft.get()方法会一直阻塞,直到call()方法执行完毕才能取到返回值。
上述主要讲解了三种常见的线程创建方式,对于线程的启动而言,都是调用线程对象的start()方法,需要特别注意的是:不能对同一线程对象两次调用start()方法。
参考:
- 文章让你彻底征服多线程开发(一)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。