关于Java多线程基础(一)

进程和线程

  • 进程:内存中运行的应用程序。每个进程有独立的内存空间,一个应用程序可以同时运行多个进程。也是程序一次执行的过程。
  • 线程:进程的执行单元(执行路径),负责当前进程中程序的执行,-一个进程至少有-一个线程。 -一个进程中可以有多个线程。
    单核心单线程cpu会在多个线程之间切换,轮流执行多个线程。 多核心多线程cpu可以同时执行线程,在多个任务之间高速切换。
    两者的联系:
    (1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
    (2)线程是操作系统可识别的最小执行和调度单位。资源分配给进程,同一进程的所有线程共享该进程的所有资源。 同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。处理机分给线程,即真正在处理机上运行的是线程。
    两者的区别:
    (1)地址空间和其他资源(如打开文件):进程间相互独立,同一进程的各线程间共享。某进程内的线程在其他进程内不可见。
    (2)通信:进程间通信IPC(管道,信号量,共享内存,消息队列,网络),线程间可以直接读写进程数据段(如全局变量)来进程通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

并行和并发

  • 并发:多个事件在同一个时间段发生(多任务在cpu上切换)
  • 并行:多个事件同一时刻发生(多个任务在多个cpu上同时执行)

线程的生命周期

New:创建线程
Runnable:分为就绪态和运行态
Blocked:阻塞状态
Waiting:等待状态
Timed_waiting: 等待状态,会有一个超时时间
Terminated:结束状态

创建线程
创建线程的方式:只有new Thread
开启线程执行单元的方式:
(1).重写Thread类下的run方法继承Thread
(2). 重写Runable类下的方法继承Runable,并实现run方法,需要再使用Thread类创建线程,并传入Runable对象
(3). 重写callable接口下的call方法继承Callable,并实现call方法,需要使用FutureTask进行一次封装,传入Callable对象,再使用Thread类创建线程,并传入FutureTask对象。
它们的区别:
继承类与实现接口的区别
a.线程类集成字Thread则不能再继承其他类,而Runnable/Callable接口可以。
b.线程类集成字Thread对于Runnable/callable来说,使用线程类内部的方法方便一些
c.实现Runnable/Callable接口的线程类的多个线程可以更加方便的访问同一变量,而Thread类则需要内部类进行替代。
Callable 和 Runnable接口的区别
a.Callable规定的方法是call(),而Runnable规定的方法是run().
b.Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
c.call()方法可抛出异常,而run()方法是不能抛出异常的。
d.运行Callable任务可拿到一个Future对象, Future表示异步计算的结果。

线程的优先级

线程的优先级默认值为5,最高为10,最低为1。
优先级高被cpu先执行概率大,并不是说优先级高的一定就会先被执行。
我们在项目开发中不能使用优先级来完成一些特定的任务。
优先级具有继承性。
优先级的特点:
(1)线程优先级的继承特性:也就是如果线程A启动线程B,那么线程A和B的优先级是一样的;
(2)线程优先级的规则性:即线程会优先级的大小顺序执行,但是不一定是优先级较大的先执行完,因为线程的优先级还有下面第三个特性:
(3)线程优先级的随机特性优先级越高,大部分情况下在多个线程的情况下优先级高的先完
成所有的任务。但是优先级并不是衡量那个线程运行结果顺序的标准,
因为cpu只是尽量将执行资源交给优先级高的线程。优先级高的线程不一定每一次都先执行完
run方法中的任务,也就是说线程优先级与打印顺序无关,他们的关系具有不确定性和随机性。

守护线程

守护线程是指在程序运行的时候在后台提供一种通用服务的线程,比如垃圾回收线程就是一个很称职的守护者,并且这种线程并不属于程序中不可或缺的部分。因 此,当所有的非守护线程结束时,程序也就终止了,同时会杀死进程中的所有守护线程。反过来说,只要任何非守护线程还在运行,程序就不会终止。
守护线程和用户线程区别:唯一的不同之处就在于虚拟机的离开,如果用户线程已经全部退出运行了,只剩下守护线程存在了,虚拟机也就退出了。 因为没有了被守护者,守护线程也就没有工作可做了,也就没有继续运行程序的必要了。

在使用守护线程时需要注意一下几点:
(1). thread.setDaemon(true)必须在thread.start()之前设置,否则会跑出一个IllegalThreadStateException异常。不能把正在运行的常规线程设置为守护线程。
(2). 在Daemon线程中产生的新线程也是Daemon的。
(3). 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

线程的中断

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait以及可中断的通道上的 I/O 操作方法后可进入阻塞状态),则在线程在检查中断标示时如果发现中断标示为true,则会在这些阻塞方法调用处抛出InterruptedException异常,并且在抛出异常后立即将线程的中断标示位清除,即重新设置为false。抛出异常是为了线程从阻塞状态醒过来,并在结束线程前让程序员有足够的时间来处理中断请求。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值