多线程笔记

多线程

基本概念:

并行与并发

* 并行:同一时间发生多个事件

* 并发:一个时间段发生多个事件

使用场景:

1.后台任务,比如游戏服务器

2.定时向大量用户(100W)发邮件

3.异步处理:发微博、记录日志等

4.分布式计算。。。。

线程和进程的区别:

进程:是指一个内存中运行的应用程序

线程:进程内部的一个独立执行单元,一个进程里可以并发多个线程

线程的生命周期:

  • 新建 :从新建一个线程对象到程序start() 这个线程之间的状态,都是新建状态;

  • 就绪 :线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;

  • 运行 :就绪状态下的线程在获取CPU资源后就可以执行run(),此时的线程便处于运行状态,运行状态的线程可变为就绪、阻塞及死亡三种状态。

  • 等待/阻塞/睡眠 :在一个线程执行了sleep(睡眠)、suspend(挂起)等方法后会失去所占有的资源,从而进入阻塞状态,在睡眠结束后可重新进入就绪状态。

  • 终止 :run()方法完成后或发生其他终止条件时就会切换到终止状态。

创建线程的方法

1、继承Thread类:

    步骤:①、定义类继承Thread;

     ②、复写Thread类中的run方法;

    目的:将自定义代码存储在run方法,让线程运行

     ③、调用线程的start方法:

    该方法有两步:启动线程,调用run方法。

  2、实现Runnable接口: 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为run 的无参方法。

   实现步骤: ①、定义类实现Runnable接口

          ②、覆盖Runnable接口中的run方法

             将线程要运行的代码放在该run方法中。

          ③、通过Thread类建立线程对象。

          ④、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。

             自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程执行指定对象的run方法就要先明确run方法所属对象

          ⑤、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

  3、通过Callable和Future创建线程:

    实现步骤:①、创建Callable接口的实现类,并实现call()方法,改方法将作为线程执行体,且具有返回值。

         ②、创建Callable实现类的实例,使用FutrueTask类进行包装Callable对象,FutureTask对象封装了Callable对象的call()方法的返回值

         ③、使用FutureTask对象作为Thread对象启动新线程。

         ④、调用FutureTask对象的get()方法获取子线程执行结束后的返回值。

继承Thread类和实现Runnable接口、实现Callable接口的区别。

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

        优势:编写简单,可直接用this.getname()获取当前线程,不必使用Thread.currentThread()方法。

        劣势:已经继承了Thread类,无法再继承其他类。

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

        优势:避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

        劣势:比较复杂、访问线程必须使用Thread.currentThread()方法、无返回值。

    实现Callable:

        优势:有返回值、避免了单继承的局限性、多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。

        劣势:比较复杂、访问线程必须使用Thread.currentThread()方法

  建议使用实现接口的方式创建多线程。

线程状态管理

1、线程睡眠---sleep:

    线程睡眠的原因:线程执行的太快,或需要强制执行到下一个线程。

    线程睡眠的方法(两个):sleep(long millis)在指定的毫秒数内让正在执行的线程休眠。

                sleep(long millis,int nanos)在指定的毫秒数加指定的纳秒数内让正在执行的线程休眠。

2、线程让步---yield:

该方法和sleep方法类似,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但是不会进入阻塞状态,而是直接进入就绪状态。相当于只是将当前线程暂停一下,然后重新进入就绪的线程池中,让线程调度器重新调度一次。也会出现某个线程调用yield方法后暂停,但之后调度器又将其调度出来重新进入到运行状态。

sleep和yield的区别:

    ①、sleep方法声明抛出InterruptedException,调用该方法需要捕获该异常。yield没有声明异常,也无需捕获。

    ②、sleep方法暂停当前线程后,会进入阻塞状态,只有当睡眠时间到了,才会转入就绪状态。而yield方法调用后 ,是直接进入就绪状态。

3、线程合并---join:

    当B线程执行到了A线程的.join()方法时,B线程就会等待,等A线程都执行完毕,B线程才会执行。

    join可以用来临时加入线程执行。

4、停止线程:

    原stop方法因有缺陷已经停用了,那么现在改如何停止线程?现在分享一种,就是让run方法结束。

    开启多线程运行,运行的代码通常是循环结构,只要控制住循环,就可以让run方法结束,也就是线程结束。

5、设置优先级:

    每个线程执行时都有一个优先级的属性,优先级高的线程可以获得较多的执行机会,而优先级低的线程则获得较少的执行机会。与线程休眠类似,线程的优先级仍然无法保障线程的执行次序。只不过,优先级高的线程获取CPU资源的概率较大,优先级低的也并非没机会执行。    

六、线程同步与锁。

  为什么要进行线程同步?

    java允许多线程并发控制,当多个线程同时操作一个可共享资源变量时(如对其进行增删改查操作),会导致数据不准确,而且相互之间产生冲突。所以加入同步锁以避免该线程在没有完成操作前被其他线程调用,从而保证该变量的唯一性和准确性。

同步的前提:

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

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

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

  4、只能同步方法,不能同步变量和类。

  5、不必同步类中所有方法,类可以拥有同步和非同步的方法。

  6、如果一个线程在对象上获得一个锁,就没有任何其他线程可以进入(该对象的)类中的任何一个同步方法。

  7、线程睡眠时,它所持的任何锁都不会释放。

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

  弊端:多个线程需要判断,消耗资源,降低效率。

《-个人笔记-》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值