多线程部分知识点

进程定义:

        是一个正在执行中的程序,每个程序都有一个执行顺序,该顺序是一个执行路径,或者叫做执行单元。

线程定义:

        是进程中的独立控制单元,是最小的执行单元,一个进程至少有一个线程。

多线程定义:

        一个进程中包含多个线程

一:为何要使用多线程?

        1. 为了更好地利用cpu资源,如果只有一个线程,则第二个任务必须要等到第一个任务执行完毕以后才可以执行。但是用多线程后, 当主线程在执行任务的时候,其他线程任务也可以执行,不需要等待。

        2. 进程之间不可以共享数据,但是线程之间可以。

        3. 系统创建进程需要为进程分配系统资源,创建线程代价更小。

        4.  Java内置了多线程功能支持,编码更加方便。

二:线程的生命周期

  1. 新建线程: 从新建一个线程对象到执行到start()语句,都属于创建阶段。
  2. 就绪状态: 这个状态下有执行资格但是没有执行权,线程对象调用start()方法后,就处于就绪状态,等到JVM里的线程调度器的调度;(不停的抢占cpu)
  3. 运行状态: 这个状态下有执行资格也有执行权,start()方法开启进程后就开始运行run()方法,进入运行代码阶段。这个时候它可以变为 就绪,阻塞,死亡三个状态。
  4. 等待/阻塞/睡眠状态:在一个线程执行了sleep()---- 睡眠方法后,该线程进入阻塞状态,当阻塞时间过去以后,回到就绪状态,再次开始抢占cpu。
  5. 死亡: run( ) 执行完或者遇到其他终止条件后,线程死亡。

三: 多线程的创建方式:

第一种:继承Thread类:

步骤:

              a)  继承Thread类,

              b)  重写 run()_方法,在方法里面写入自己需要运行的代码。

              c)  调用start()方法:

                该方法两步:开启线程  ,调用run( ) 执行代码

 第二种:实现Runnable接口:

步骤:

  1. 定义实现Runnable接口。
  2. 重写 run()_方法,在方法里面写入自己需要运行的代码。
  3. 创建Runnable对象。
  4. 通过Thread创建线程。并将Runnable对象交给Thread类的构造函数。
  5. 调用Thread的start方法开启线程 并 执行run() 方法。

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

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

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

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

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

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

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

3.实现Callable:

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

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

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

五: 一个线程安全的案例:

没锁的时候会有线程安全问题:

        线程开启之后 当

        窗口一 先执行run() 方法  他会在sleep(睡眠方法)执行后进入睡眠,该时候不影响其他线程执行。窗口二也是这样。

        当窗口三执行到这里的时候,窗口一醒来继续执行 ticket++,这个时候变为1号票,但是没有输出。

        因为线程执行具有随机性,你不知道什么时候执行那个线程。如果这个时候窗口二 抢夺了cpu 那它继续执行 ticket++,这个时候变为2号票  

        如果这个时候输出了 那窗口一 和二  都出的是二号票。

解决方法: 加上锁synchronized(锁对象)
         锁默认打开  一个线程进去    锁关闭   该线程执行完   锁开启

为什么要进行线程同步?

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

六.同步方法:

代码:

Ctrl+alt+m  变成同步方法:

同步方法
作用:把出现线程安全问题的核心方法给上锁。
原理:每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行。

同步方法底层原理
同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码。
如果方法是实例方法:同步方法默认用this作为的锁对象。但是代码要高度面向对象!
如果方法是静态方法:同步方法默认用类名.class作为的锁对象。

是同步代码块好还是同步方法好一点?
同步代码块 锁的范围更小,同步方法 锁的范围更大。

七:手动上锁(LOCK锁):

        无论是同步代码块还是同步方法,虽然都锁住了对象,但是都无法直接看到在那里上了锁,在那里释放了锁。为了更加清晰的看到那里上了锁,在那里释放了锁,我们采用了Lock锁的方法对对象进行上锁。

实现方法(手动上锁):void lock(): 获得锁             void  unlock(): 释放锁

注意:Lock是接口无法直接实例化,需要采用他的实现类ReentrantLock来实例化。

示例代码:

上面代码结果显示有问题(因为程序无法进行完毕):

解决方法:

        将整个锁下面的执行语句放在异常里面  利用异常的 finally{  } 来把释放锁放在里面  

        finally{  }-----它里面的代码是一定会执行的

代码示例:

八:线程的6大状态

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值