黑马程序员——多线程

------ Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

多线程

一、多线程的概念

    进程:是一个正在运行中的程序。每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。
    线程:就是进程中的一个独立的控制单元,线程子在控制着进程的执行,一个进程中至少有一个线程。
    JVM启动时会有一个进程java.exe,该进程中至少一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中,该线程称之为主线程。
    扩展:jvm启动时其实不止一个线程,还有负责垃圾回收机制的线程。
二、多线程的存在的意义
    多线程可以使程序中不同的部分产生同时运行的效果,可以提高运行的效率。
三、多线程的创建方式
    方法1:
           1、定义类继承Thread类,覆盖Thread类中的run方法。
           2、创建一个子类对象。(等于创建一个线程)
           3、调用线程的start方法,该方法有两个作用,启动线程并调用run方法。
    代码如下:
             
public class Test1 extends Thread {
 
 public void run()
 {
  System.out.println("方法执行了");
 }
 
 public static void main(String[] args)
 {
  Test1 test=new Test1(); 
  test.start();
  }
     多线程运行时,CPU在做着快速的切换,以达到看上去是同时运行的效果。这就是多线程的随机性,谁抢到CPU谁执行。
     方法2:
            1、定义实现Runnable接口的类,实现run()方法。
            2、通过Thread类简历线程对象。
            3、将Runnable接口的实现类对象作为参数传递给Thread类的构造函数。
            4、调用Thread类对象的start()方法开启线程并调用Runnable接口实现类中的run()方法。
     代码如下:
public class Test1 implements Runnable {
 
 public void run()
 {
  System.out.println("方法执行了");
 }
 
 public static void main(String[] args)
 {
  Test1 test=new Test1(); 
  Thread td=new Thread(test);
  td.start();
   }
      两种多线程创建方式的区别:
     因为java中不支持多继承,当一个类已经有了自己的父类时,就不能使用继承的方式实现多线程,只能使用实现接口的方式实现多线程。
     两种方式中线程代码存放的位置不同,使用继承方式线程代码存放在Thread子类的run方法中;使用实现方式线程代码存放在Runnable接口的子类run方法中。
四、run和start的特点
     run方法:
     Thread类用于描述线程。该类定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。覆盖run方法的目的就是将自定义的代码存储在run方法中,让线程运行。
     start方法:
     start方法用来开启线程并执行run方法,如果直接调用run方法,那么执行run方法中代码的是主线程,而不是自己创建的线程。
五、线程运行的状态
     1、被创建:创建一个Thread对象或者创建一个Thread子类对象。
     2、运行:具备执行资格同时拥有执行权的状态。
     3、冻结:利用sleep(时间)方法让线程睡眠自定义的时间,时间到后线程自动苏醒,进入临时状态;利用wait()方法让线程进入等待状态,利用notify()方法可以将其唤醒,进入临时状态。
     4、销毁:利用stop()方法销毁线程。或者run方法执行结束时线程自动销毁(stop方法已过时,基本不再使用)。
     5、阻塞:线程具备运行资格但没有执行权的状态。
六、获取线程对象及名称
     线程都有自己默认的名称,显示为Thread-编号的形式,编号从0开始,可以利用this.getName()方法获得当前线程的名称,也可以利用this.setName()方法自定义当前线程的名称,还可以通过父类的构造函数初始化线程名称。
     通过Thread.currentThread()方法可以获得当前线程对象,此方法等同于this关键字。
七、线程的安全和同步
     当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,这时另一个线程参与进来执行,会导致共享数据出错,这样的程序不安全。
     解决方式:
     对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行,如此就能解决线程的安全隐患。
     1、这时就要使用到同步代码块:synchronized(对象){需要被同步的代码}
     2、还可以将synchronized当做修饰符放在函数上使函数具有同步性,同步函数使用的锁是this(静态同步函数使用的锁不是this,而是该函数所在类的字节码文件对象)。
     同步代码块中,对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取cpu的执行权也进不去,因为没有获取锁。
     线程同步的前提:
     1、必须要有两个或者两个以上的线程。
     2、必须是多个线程使用同一个锁。
     线程同步的利弊:
     利:解决了线程安全问题。
     弊:多个线程都需要判断锁,较为消耗资源。
八、死锁现象
     死锁现象通常出现在同步中嵌套同步而锁却不同的时候,持有A锁的线程想进入B中,但持有B锁的线程也想进入A中,但因为双方手中所持有的锁都没有打开,会导致程序停滞,我们要尽量避免这种情况发生。
九、线程间通讯
     线程间通讯其实就是多个线程在操作同一个资源,但是操作的动作不同。
     在这种情况下一定要考虑是否把共享数据代码都放进了锁中,使用的锁是否相同,以避免程序发生安全隐患。
十、停止线程
      想要让线程停止,只有两种方法,要么使用stop方法强制停止线程,要么使run方法结束。
      stop方法因为安全问题已经过时而不再使用,那么唯一的方法就是使run方法结束。开启多线程运行,运行代码通常是循环结构,只要控制住循环,就可以让run方法结束,进而让线程结束。
      特殊情况:如果当线程处于了冻结状态,这时就无法再控制循环,无法停止线程的运行。当没有指定的方式让冻结的线程恢复到运行状态时,就需要对冻结进行清除,强制让线程恢复到运行状态中来,这样就可以操作循环让线程结束。
     Thread类提供了该方法:interrupt();
十一、守护线程
      使用setDaemon(true)方法可以将线程变成守护线程,该方法必须在启动线程前调用,守护线程在开启与运行上与普通线程没有区别,但在运行的线程全部为守护线程时,jvm会自动退出。
十二、join方法
      当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会继续执行。join可以用来临时加入线程执行。

主要内容:本文详细介绍了一种QRBiLSTM(分位数回归双向长短期记忆网络)的时间序列区间预测方法。首先介绍了项目背景以及模型的优势,比如能够有效利用双向的信息,并对未来的趋势上限和下限做出估计。接着从数据生成出发讲述了具体的代码操作过程:数据预处理,搭建模型,进行训练,并最终可视化预测结果与计算分位数回归的边界线。提供的示例代码可以完全运行并且包含了数据生成环节,便于新手快速上手,深入学习。此外还指出了模型未来发展的方向,例如加入额外的输入特性和改善超参数配置等途径提高模型的表现。文中强调了时间序列的标准化和平稳检验,在样本划分阶段需要按时间序列顺序进行划分,并在训练阶段采取合适的手段预防过度拟合发生。 适合人群:对于希望学习和应用双向长短时记忆网络解决时序数据预测的初学者和具有一定基础的研究人员。尤其适用于有金融数据分析需求、需要做多一步或多步预测任务的从业者。 使用场景及目标:应用于金融市场波动预报、天气状况变化预测或是物流管理等多个领域内的决策支持。主要目的在于不仅能够提供精确的数值预计还能描绘出相应的区间概率图以增强结论置信程度。 补充说明:本教程通过一个由正弦信号加白噪构造而成的简单实例来指导大家理解和执行QRBiLSTM流程的所有关键步骤,这既方便于初学者跟踪学习,又有利于专业人士作为现有系统的补充参考工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值