多线程

本文详细介绍了Java中进程与线程的概念,包括多线程的好处与弊端,并探讨了创建线程的三种方式及其优缺点。此外,还讲解了线程的状态、同步机制以及解决多线程安全问题的方法。

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

 

1.进程和线程的概念

进程:正在进行中的程序(直译),是任务的基本单位。一个进程中至少要有一个线程。

线程:就是进程中一个负责程序执行的控制单元(执行路径),是cpu的基本单位。每一个线程都有自己运行的内容。这个内容可以称为线程要执行的任务。

多线程:一个进程中可以多执行路径。

多线程有什么好处呢?比如有三个线程分别为Thread1、Thread2、Thread3,传统的单线程是按照从上往下的顺序依次执行,Thread1执行不完,另外的线程就需要等待。小伙伴们不乐意了,于是就开始你运行一会,我运行一会,多么欢乐和谐。这就是多线程。到底谁执行呢?执行多长时间呢?这是由CPU决定的,就像皇帝想翻哪个妃子的牌子决定权在皇帝那里。

开启多个线程是为了同时运行多部分代码。

多线程好处:解决了多部分同时运行的问题。

多线程的弊端:线程太多会导致效率的降低。

其实应用程序的执行都是cpu在做着快速的切换完成的,这个切换是随机的。

JVM启动时就启动了多个线程,至少有两个线程可以分析的出来。

1,执行main函数的线程,

该线程的任务代码都定义在main函数中。

2,负责垃圾回收的线程。

2.创建线程方式一:继承Thread类

步骤:

1,定义一个类继承Thread类。

2,覆盖Thread类中的run方法。

3,直接创建Thread的子类对象创建线程。

4,调用start方法开启线程并调用线程的任务run方法执行。

可以通过Thread的getName获取线程的名称  Thread-编号(从0开始)

主线程的名字就是main。

 start() 启动线程

 run()  线程启动后执行的函数

 interrupt() 中断线程

 join()  合并线程

 sleep(long millis) 让当前线程休眠

 setDaemon(boolean on) 设置线程为守护线程

 setPriority(int newPriority) 设置线程优先级

 setName(String name) 设置线程名

 getName() 可以获取线程对象的标志名,线程对象默认标志名是 Thread-编号,编号从0开始。

 static Thread currentThread() 返回当前正在执行的线程对象的引用

3.创建线程方式二:实现Runnable接口

 步骤: 

 1.定义类实现 Runnable 接口 

 2.覆盖 Runnable 接口中的 run 方法 

 3.通过 Thread 类建立线程对象 

 4.将 Runnable 接口的子类对象作为参数传递给 Thread 类对象的构造函数 

 5.调用 Thread 类的 start 方法开启线程 

  

 总结: Runnable 接口是把 Thread 中未知功能封装起来了,让别的类来实现 Runnalbe 接口之后,再把对象的应用传给 Thread 类对象,那么就实现了 Thread 对象启动新线程后去运行,run 中的方法。Runnable 接口对 Thread 类的功能进行了扩展。 

4.为什么要有Runnable接口的出现?

 1:通过继承Thread类的方式,可以完成多线程的建立。但是这种方式有一个局限性,如果一个类已经有了自己的父类,就不可以继承Thread类,因为java单继承的局限性。

 可是该类中的还有部分代码需要被多个线程同时执行。这时怎么办呢?

 只有对该类进行额外的功能扩展,java就提供了一个接口Runnable。这个接口中定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码。

 所以,通常创建线程都用第二种方式。

  因为实现Runnable接口可以避免单继承的局限性。

 2:其实是将不同类中需要被多线程执行的代码进行抽取。将多线程要运行的代码的位置单独定义到接口中。为其他类进行功能扩展提供了前提。

 所以Thread类在描述线程时,内部定义的run方法,也来自于Runnable接口。

 实现Runnable接口可以避免单继承的局限性。而且,继承Thread,是可以对Thread类中的方法,进行子类复写的。但是不需要做这个复写动作的话,只为定义线程代码存放位置,实现Runnable接口更方便一些。所以Runnable接口将线程要执行的任务封装成了对象。

 实现方式和继承方式有什么区别?考面试题

 实现方式好处:避免了单继承的局限性,在定义线程时建议使用实现方式,

 继承thread:线程代码存放在thread的子类run方法中。

 实现runnable:线程代码存放在接口的子类的run方法。

5.线程的状态:

被创建:start()

运行:具备执行资格,同时具备执行权;

冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;

临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;

死亡:stop()

 

多线程代码示例,以四个窗口卖火车票为例:

[java] view plaincopy

  1. <span style="font-weight: normal;"><span style="font-size:14px;">class Ticket implements Runnable  
  2. {  
  3.     private  int tick = 1000;  
  4.     Object obj = new Object();  
  5.     public void run()  
  6.     {  
  7.         while(true)  
  8.         {  
  9.             synchronized(obj)  
  10.             {  
  11.                 if(tick>0)  
  12.                 {  
  13.                     //try{Thread.sleep(10);}catch(Exception e){}  
  14.                     System.out.println(Thread.currentThread().getName()+"....sale : "+ tick--);  
  15.                 }  
  16.             }  
  17.         }  
  18.     }  
  19. }  
  20. class  TicketDemo2  
  21. {  
  22.     public static void main(String[] args)   
  23.     {  
  24.         Ticket t = new Ticket();  
  25.         Thread t1 = new Thread(t);  
  26.         Thread t2 = new Thread(t);  
  27.         Thread t3 = new Thread(t);  
  28.         Thread t4 = new Thread(t);  
  29.         t1.start();  
  30.         t2.start();  
  31.         t3.start();  
  32.         t4.start();  
  33.     }  
  34. }</span></span>  

 

6.同步

 

多线程安全问题的原因:

    当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行。导致共享数据的错误。

解决办法:

对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。

java提供了同步的方法来解决那个令人腿疼的-1号票问题。

synchronized(对象)//任意对象都可以。这个对象就是锁。

{

    需要被同步的代码

}

同步函数:其实就是将同步关键字定义在函数上,让函数具备了同步性。

同步函数是用的哪个锁呢?

函数都有自己所属的对象this,所以同步函数所使用的锁就是this锁。

当同步函数被static修饰时,这时的同步用的是哪个锁呢?

静态函数在加载时所属于类,这时有可能还没有该类产生的对象,但是该类的字节码文件加载进内存就已经被封装成了对象,这个对象就是该类的字节码文件对象。

所以静态加载时,只有一个对象存在,那么静态同步函数就使用的这个对象。

这个对象就是 类名.class

同步代码块和同步函数的区别?

同步代码块使用的锁可以是任意对象。

同步函数使用的锁是this,静态同步函数的锁是该类的字节码文件对象。

在一个类中只有一个同步,可以使用同步函数。如果有多同步,必须使用同步代码块,来确定不同的锁。所以同步代码块相对灵活一些。

同步的前提:

1,必须要有两个或者两个以上的线程。

2,必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行。

 

好处:解决了多线程的安全问题。

弊端:多个线程需要判断锁,较为消耗资源,产生了死锁。

[java] view plaincopy

  1. <span style="font-size:14px;">public class DeadLockTest {  
  2.     public static void main(String[] args) {  
  3.     Thread t1=new Thread(new Test(true));  
  4. Thread t2=new Thread(new Test(false));  
  5. t1.start();  
  6. t2.start();  
  7.     }  
  8. }  
  9. class Test implements Runnable  
  10. {  
  11.   private boolean flag;  
  12.   Test11(boolean flag)  
  13.   {  
  14.       this.flag=flag;  
  15.   }  
  16.   public void run()  
  17.   {  
  18.       if(flag)  
  19.       { while(true)  
  20.       {  
  21.           synchronized(MyLock.locka)  
  22.           {  
  23.               System.out.println("if locka");  
  24.               synchronized(MyLock.lockb)  
  25.               {  
  26.                   System.out.println("if lockb");  
  27.               }  
  28.           }  
  29.       }  
  30.       }  
  31.       else{  
  32.           while(true)  
  33.           {  
  34.           synchronized(MyLock.lockb)  
  35.           {  
  36.               System.out.println("else lockb");  
  37.               synchronized(MyLock.locka)  
  38.               {  
  39.                   System.out.println("else locka");  
  40.               }    
  41.           }  
  42.       }  
  43.   }  
  44. }  
  45. }  
  46. class MyLock  
  47. {  
  48.  static  Object locka=new Object();  
  49.  static  Object lockb=new Object();  
  50. }</span>  
  51. 实现线程的第三种方式

     * JDK5之后提供了新的一种实现线程的方式:
     * 
     * 步骤:
     * 1.自定义一个类,实现自:Callable接口
     * 2.重写里面的call()方法;
     * 3.测试类:
     * 1).需要JDK5的线程池来启动:
     */
    public class Demo {
    public static void main(String[] args) {
    ExecutorService ser = Executors.newFixedThreadPool(2);
    ser.submit(new MyCallable());
    ser.shutdown();
    }
    }
  52. import java.util.concurrent.Callable;
    public class MyCallable implements Callable {
    @Override
    public Object call() throws Exception {
    for(int i = 0 ;i < 10 ;i ++){
    System.out.println("i = " + i);
    }
    return null;
    }
    }
内容概要:本文介绍了基于贝叶斯优化的CNN-LSTM混合神经网络在时间序列预测中的应用,并提供了完整的Matlab代码实现。该模型结合了卷积神经网络(CNN)在特征提取方面的优势与长短期记忆网络(LSTM)在处理时序依赖问题上的强大能力,形成一种高效的混合预测架构。通过贝叶斯优化算法自动调参,提升了模型的预测精度与泛化能力,适用于风电、光伏、负荷、交通流等多种复杂非线性系统的预测任务。文中还展示了模型训练流程、参数优化机制及实际预测效果分析,突出其在科研与工程应用中的实用性。; 适合人群:具备一定机器学习基基于贝叶斯优化CNN-LSTM混合神经网络预测(Matlab代码实现)础和Matlab编程经验的高校研究生、科研人员及从事预测建模的工程技术人员,尤其适合关注深度学习与智能优化算法结合应用的研究者。; 使用场景及目标:①解决各类时间序列预测问题,如能源出力预测、电力负荷预测、环境数据预测等;②学习如何将CNN-LSTM模型与贝叶斯优化相结合,提升模型性能;③掌握Matlab环境下深度学习模型搭建与超参数自动优化的技术路线。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点关注贝叶斯优化模块与混合神经网络结构的设计逻辑,通过调整数据集和参数加深对模型工作机制的理解,同时可将其框架迁移至其他预测场景中验证效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值