Java 并发编程(一)

一、线程与进程

  • 定义
    • 进程:具有独立功能的程序的一次执行过程,是系统进行资源分配和调度的一个独立单位
    • 线程:是进程的一个实体,是CPU调度和分派的基本单位,比进程更小的能够独立运行的基本单位。线程基本上不拥有系统资源,只拥有运行过程中必不可少的资源(程序计数器、寄存器、栈)可与同属一个进程的其他线程共享进程所拥有的全部资源(代码段、数据段、堆空间、进程打开的文件)。
  • 关系
    • 一个线程可以创建和销毁另一个线程,同一个进程中的多个线程之间可以并发执行。线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
  • 区别
    • 一个程序至少有一个进程,一个进程至少有一个线程
    • 线程的划分尺度小于进程,使得多线程的并发性高
    • 进程在执行的过程中拥有独立的内存单元,而多线程共享内存,从而极大地提高类执行效率
    • 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
    • 多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。

二、线程创建

  • 继承Thread类,重写run()方法
  • 实现Runnable接口,并实现该接口的run()方法
  • 实现Callable接口,重写call()方法

Callable 接口实际是属于Executor框架中的,相比Runnable具有更加强大的功能:

  • Callable 可以提供返回值, Runnable 没有返回值
  • Callable中的call方法可以抛除异常,而Runnable方法中的run方法不能抛出异常
  • 运行Callable 可以拿到一个Future对像,Future对象表示异步计算的结果,他提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数的返回值,在这种情况下就可以使用Future来监视目标线程调用call()方法的情况,但调用Future的get()方法以获取结果时,当前线程就会阻塞,直到call()方法的返回结果。

使用实例

public class TestCallable {  
    //创建线程类
    public static class MyTestCallable  implements Callable {  
        public String call() throws Exception {  
             retun "Hello World";
         }  
     }  

    public static void main(String[] args) {  
          MyTestCallable mMyTestCallable= new MyTestCallable();  
          ExecutorService mExecutorService = Executors.newSingleThreadPool();  
          Future mfuture = mExecutorService.submit(mMyTestCallable);  
          try { 
              //等待线程结束,并返回结果
              System.out.println(mfuture.get());  
          } catch (Exception e) {  
             e.printStackTrace();
          } 
    }  
}

三、线程的运行状态

image

线程共包括以下5种状态。

    1. 新建状态(New) : 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()。
    1. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。
    1. 运行状态(Running) : 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。
    1. 阻塞状态(Blocked) : 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:
    • (01) 等待阻塞 -- 通过调用线程的wait()方法,让线程等待某工作的完成。
    • (02) 同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
    • (03) 其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
    1. 死亡状态(Dead) : 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

更多

1. Java线程的5种状态及切换(透彻讲解)
2. 死磕Java系列博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容