java 并行程序基础

进程和线程

  • 进程:,计算机中的程序关于某数据集合的一次运行过冬,是系统进行资源分配和调度的基本单位,是操作系统结构的基础,是线程的容器
  • 线程:轻量级进程,程序执行的最小单位
  • 线程生命周期:
    在这里插入图片描述
  • 线程状态:
    NEW:刚创建的线程,还没开始执行(new Thread())
    Runnbale:线程执行start()方法时候,进入RUNNABLE状态,表示线程需要的资源已经准备好
    BLOCKED:当执行过程中遇到synchronized同步快,就会进入BLOCKED阻塞状态,线程暂停执行,指到获得请求的锁
    WAITING:无时间限制的等待
    TIME_WAITING:有时间限制的等待
    等待的线程正是在等待一些特殊的事件,比如wait()方法等待的线程在等待notify()方法。join()方法等待的线程则会等待目标线程的终止。当等待结束后,线程会再次执行,进入RUNNABLE状态
    TERMINATED:线程执行完毕

线程的基本操作

1. 新建线程

  • 继承Thread类
    使用创建线程直接使用new关键创建一个线程对象:
    class MyThread extend Thread{}
    Thread t1 = new MyThread();
    t1.start();
    start()方法会新建一个线程并让这个线程执行run()方法
    注意:如果线程对象直接调用run()方法时,可以通过编译,也能正常执行,但是不能新建线程,而是作为一个普通的方法调用
    一般情况下是要重载run()方法,因为Thread的run()方法没有业务逻辑,具体需求需要重载run()方法,然后添加业务逻辑代码
  • 实现Runnable接口
    Runnable接口只有一个run方法
    此外,Thread类有一个构造方法,参数就是Runnable实例
    public Thread(Runnable target)
    继承Runnable接口创建线程:
    public MyRunnable implements Runnable{}
    Thread t1 = new Thread(new MyRunnable);
    t1.start();

2. 终止线程

一般情况下,线程执行完毕后就会结束,无须手工关闭。但是对于一些常驻系统,通常不会正常终结
Thread提供了stop()方法,立即将一个线程结束,但是这是一个被废弃的方法,因为stop()方法会强行把执行到一半的线程终止,会导致数据错乱等问题
stop()会直接终止线程,并且会立即释放这个线程所持有的锁。在高并发多线程的程序中不要轻易使用stop()方法来停止一个线程
停止线程:可以根据具体需求,提供一个需要停止线程的flag,然后判断这个flag的值,在适当的时候break,就可以停止线程

3. 线程中断

线程中断并不会使形成立即退出,而是给线程发送一个通知,告知目标线程,需要退出,线程接到通知,何时退出就是目标线程自己决定
线程中断三个方法:

Thread.interrupt():通知目标线程中断,设置中断标志位
Thread.isInterrupted():判断当前线程时候有被中断
第三个Thread.interrupted():判断当前线程的中断状态,同时也会清除当前线程的中断标志位状态
在这里插入图片描述
sleep()方法:让线程休眠若干时间,会抛出InterruptedException中断异常,当sleep()休眠时,如果被中断就会抛出异常
sleep()由于中断而抛出异常,会清除中断标记。可以通过静态Thread.interrupted()中断方法来判断是否处于中断状态

4. 等待和通知

Object类中提供了wait()和notify()方法
在这里插入图片描述wait():进入线程等待状态,线程停止继续执行。进入到object对象的等待队列(可能会有多个线程)
notify();通知线程可以结束等待状态,线程继续执行。被调用时,会从object对象的等待队列中,随机选择一个线程,并将其换新。这个选择是不公平的
notifyAll():唤醒等待队列中所有的等待的线程
注意:wait()方法必须包含在对应synchronzied语句中,无论是wait()还是notify()都需要首先获得目标对象的一个监视器(锁)
在这里插入图片描述
在这里插入图片描述
当wait()和notif()方法执行完后,会释放监视器(锁)。这样才不会导致其他等待的线程陷入长期休眠而无法正常执行

slee和wait的区别:
都是让线程等待若干时间
不同点:
wait方法可以被唤醒,还会释放对象的锁,属于object类
sleep类不会释放任何资源,属于Thread类

5. 挂起(suspend)和继续执行(resume)线程

线程挂起必须等到resume()操作后,才能继续指定。这两个方法已被标注为废弃方法
suspend()方法会导致线程暂停的同时并不会释放锁资源,而当其他线程刚要访问被锁住的资源的时候,就会导致线程阻塞,无法正常继续运行。直到线程进行了resume()操作,被挂起的线程才能继续。如此被阻塞的线程才能继续执行。
特殊情况:resume()在suspend()之前被执行,那么被挂起的线程很难有机会被继续执行,而且说占用的说不会被释放,就会造成系统无法正常工作
着重之点:被挂起的线程的状态还是Runnable,这会对于判断线程状态造成很大干扰
实现线程挂起和继续执行可以通过设置一个flag,通过配合wait()和notify()方法实现。当线程挂起的时候,执行wait()进行等待,当继续执行的时候,执行notfiy()通知,并且继续执行线程

6. 等待线程结束(join)和谦让(yield)

一个线程的输入可能非常依赖于另外一个或多个线程的输出,这时候,这个线程就需要等待依赖线程执行完毕,才能继续执行,可以通过join()来实现
public final void join() throws InterruptedExcetion:
无限等待,会一直阻塞当前线程,直到目标线程执行完毕
public final synchronized void join(long millis) throw InterruptedException
给定一个最大等待时间,如果超过给定时间目标线程还在执行,当前线程会因为超时而继续往下执行

join的本质是让调用线程在当前线程对象上进行等待
注意:不要在应用程序中,在Thread对象实例上使用wait()或者notif()等方法,因为可能会影响系统API的工作

public static native void yield();
执行这个方法之后,会使当前线程让出CPU。当前线程让出CPU后,还会进行CPU资源的争夺,是否会再次被分配到,就不一定过了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值