Java并发编程-线程基础( 二 )

测试代码:
@Testpublic void callable() throws ExecutionException, InterruptedException {//创建线程池ExecutorService service = Executors.newFixedThreadPool(1);//传入Callable实现同时启动线程Future submit = service.submit(new CallableDemo());//获取线程内容的返回值 , 便于后续逻辑System.out.println(submit.get());//关闭线程池service.shutdown();//主线程System.out.println("这是main主线程:" + Thread.currentThread().getName());try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}}结果:
Java并发编程-线程基础文章插图
有的时候 , 我们可能需要让一步执行的线程在执行完成以后 , 提供一个返回值给到当前的主线程 , 主线程需要依赖这个值进行后续的逻辑处理 , 那么这个时候 , 就需要用到带返回值的线程了
关于线程基础知识的如果有什么问题的可以在网上查找资料学习学习!这里不再阐述
2. 线程的生命周期

  • Java 线程既然能够创建 , 那么也势必会被销毁 , 所以线程是存在生命周期的 , 那么我们接下来从线程的生命周期开始去了解线程 。
2.1 线程的状态2.1.1 线程六状态认识线程一共有 6 种状态(NEW、RUNNABLE、BLOCKED、WAITING、TIME_WAITING、TERMINATED)
  • NEW:初始状态 , 线程被构建 , 但是还没有调用 start 方法
  • RUNNABLED:运行状态 , JAVA 线程把操作系统中的就绪和运行两种状态统一称为“运行中”
  • BLOCKED:阻塞状态 , 表示线程进入等待状态, 也就是线程因为某种原因放弃了 CPU 使用权 , 阻塞也分为几种情况 等待阻塞:运行的线程执行 wait 方法 , jvm 会把当前线程放入到等待队列? 同步阻塞:运行的线程在获取对象的同步锁时 , 若该同步锁被其他线程锁占用了 , 那么 jvm 会把当前的线程放入到锁池中 其他阻塞:运行的线程执行 Thread.sleep 或者 t.join 方法 , 或者发出了 I/O 请求时 , JVM 会把当前线程设置为阻塞状态 , 当 sleep 结束、join 线程终止、io 处理完毕则线程恢复
  • TIME_WAITING:超时等待状态 , 超时以后自动返回
  • TERMINATED:终止状态 , 表示当前线程执行完毕

Java并发编程-线程基础文章插图
2.1.2 代码实操演示
  • 代码:
public static void main(String[] args) {////TIME_WAITING 通过 sleep wait(time) 来进入等待超时中new Thread(() -> {while (true){//线程执行内容try {TimeUnit.SECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}},"Time_Waiting").start();//WAITING ,线程在 ThreadStatus 类锁上通过 wait 进行等待new Thread(() -> {while (true){synchronized (ThreadStatus.class){try {ThreadStatus.class.wait();} catch (InterruptedException e) {e.printStackTrace();}}}},"Thread_Waiting").start();//synchronized 获得锁 , 则另一个进入阻塞状态 blockednew Thread(() -> {while (true){synchronized(Object.class){try {TimeUnit.SECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}},"Object_blocked_1").start();new Thread(() -> {while (true){synchronized(Object.class){try {TimeUnit.SECONDS.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}},"Object_blocked_2").start();}启动一个线程前 , 最好为这个线程设置线程名称 , 因为这样在使用 jstack 分析程序或者进行问题排查时 , 就会给开发人员提供一些提示


推荐阅读