java并发编程(一)并发基础

java并发编程(一)并发基础

何为进程?
进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。

在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程中的一个线程,也称主线程。
何为线程?
线程与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
为什么要使用多线程呢?
从计算机底层来说: 线程可以比作是轻量级的进程,是程序执行的最小单位,线程间的切换和调度的成本远远小于进程。另外,多核 CPU 时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。
从当代互联网发展趋势来说: 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。
使用多线程可能带来什么问题?
并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、上下文切换、死锁还有受限于硬件和软件的资源闲置问题。
线程的生命周期和状态
在这里插入图片描述
线程死锁
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
如下图所示,线程 A 持有资源 2,线程 B 持有资源 1,他们同时都想申请对方的资源,所以这两个线程就会互相等待而进入死锁状态。
在这里插入图片描述
学过操作系统的朋友都知道产生死锁必须具备以下四个条件:

  • 互斥条件:该资源任意一个时刻只由一个线程占用。
  • 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
    4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
    们只要破坏产生死锁的四个条件中的其中一个就可以避免死锁了

** sleep() 方法和 wait() 方法区别和共同点**

  • 两者最主要的区别在于:sleep 方法没有释放锁,而 wait 方法释放了锁 。
  • 两者都可以暂停线程的执行。
  • Wait通常被用于线程间交互/通信,sleep 通常被用于暂停执行。
  • wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。或者可以使用wait(longtimeout)超时后线程会自动苏醒。
    等待线程执行终止的 join 方法
    在项目实践中经常会遇到一个场景,就是需要等待某几件事情完成后才能继续往下执 行, 比如多个线程加载资源, 需要等待多个线程全部加载完毕再汇总处理。 Thread 类中有 一个join 方法就可以做这个事情,前面介绍的等待通知方法是 Object 类中的方法, 而 join 方法则是 Thread 类直接提供的。
    让出 CPU 执行权的 yield 方法
    当一个线程调用 yield 方法时, 当前线程会让出 CPU 使用权,然后处于就绪状态,线 程调度器会从线程就绪队列里面获取一个线程优先级最高的线程,当然也有可能会调度到 刚刚让出 CPU 的那个线程来获取 CPU 执行权。
    线程中断
  • void interrupt() 方法: 中断线程, 例如,当线程 A 运行时,线程 B 可以调用钱程 A 的 interrupt() 方法来设置线程 A 的中断标志为 true 并立即返回。设置标志仅仅是设 置标志, 线程 A 实际并没有被中断, 它会继续往下执行。 如果线程 A 因为调用了 wait 系列函数、 join 方法或者 sleep 方法而被阻塞挂起,这时候若线程 B 调用线程 A 的 interrupt() 方法,线程 A 会在调用这些方法的地方抛出 InterruptedException 异 常而返回。
  • boolean isinterrupted() 方法: 检测当前线程是否被中断,如果是返回 true, 否则返
    回 false。
  • boolean interrupted() 方法: 检测当前线程是否被 中 断, 如果是返回 true, 否则返 回 false。与 islnterrupted 不同的是,该方法如果发现当前线程被中断, 则会清除 中断标志,并且该方法是 static 方法, 可 以通过 Thread 类直接调用。另 外从下面 的代码可以知道, 在 interrupted()内部是获取当前调用线程的中断标志而不是调用 interrupted() 方法的实例对象的中断标志。
    守护线程与用户线程
    Java 中的线程分为两类,分别为 daemon 线程(守护线程〉和 user 线程(用户线程)。 在 NM 启动时会调用 main 函数, main 函数所在的线程就是一个用户线程,其实在 NM 内部同时-还启动了好多守护线程, 比如垃圾回收线程。那么守护线程和用户线程有什么区 别呢?区别之一是当最后一个非守护线程结束时, JVM会正常退出,而不管当前是否有 守护线程,也就是说守护线程是否结束并不影响 NM 的退出。言外之意,只要有一个用 户线程还没结束, 正常情况下 JVM就不会退出。
public static void main(String[] args) { 
Thread daemonThread = new Thread (口ew Runnable( ) { public void run( ) { 
} 
});
//设置为守护线程 
daemonThread.setDaemon(true) ; 
daemonThread. start (); 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值