Java多线程全知识(除线程池外)

时间:2020-09-24 21:18:25   收藏:0   阅读:43

多线程

进程与线程

实现多线程的3种方法

  1. 继承Thread类(不推荐)

    • 创建类,继承Thread类

    • 重写run()方法

    • 创建对象,使用start()方法启动线程

    Java有单继承的局限性,尽量不使用这种方法

  2. 实现Runnable接口(推荐使用)

    • 创建类,实现Runnable接口

    • 重写run()方法

    • 创建对象,并将其作为Thread类的构造参数,创建Thread类,调用start()方法启动线程

    这种方法避免使用继承,缓解了Java单继承的局限性,并且使用静态代理,可以节约资源

    使用到了静态代理,一个资源(对象),多次代理(Thread类代理、多个线程使用一个对象)

  3. 实现Callable接口(投入工作后会使用到,前期不使用)

线程的状态以及操作

状态

技术图片

操作

线程状态观测

线程优先级

守护线程

线程同步

多个线程操作同一个资源,会导致一些不安全的事件发生。例如,银行取钱,两个人同时取一个银行卡的钱,两人取钱的总额大于银行卡余额,结果余额就会出现负数。这就是一种严重的错误。

所以我们要用到队列

当一个线程操作一个资源的时候,给他一个锁,这样来防止同一时间有其他线程来操作这个资源。在使用过资源后,释放锁,交由下一个线程。也就形成了一个队列。

加锁

  1. 使用synchronized关键字

    每个对象都有一把锁

    1. 对方法加锁

      public synchronized void method(){

      逻辑代码

      }

      这样就实现对方法加锁,在线程调用这个方法的时候,就会默认使用this对象(线程对象)来加锁

    2. 代码块加锁

      @Override

      public void run(){

      synchronized (一个对象,一般使用被操作的资源){

      逻辑代码

      }

      }

      当运行到代码块时,括号里的对象将会被锁上,逻辑代码执行完之前,其他线程不能访问

  2. 使用Lock(接口)锁

    ReentrantLock类实现了Lock接口

    1. 使用方法

      class testLock implements Runnable{

      private final ReentrantLock lock =new ReentrantLock();

      @Override

      public void run() {

      while(true){

      try {

      lock.lock();//加锁

      逻辑代码

      }finally {

      lock.unlock();//解锁

      }

      }

    synchronized与Lock的区别,前者是隐性的上锁开锁,在进入被其修饰的代码时自动上锁,在跳出代码块后自动解锁

    而Lock则是需要手动的上锁解锁,是显性的

死锁

两个线程在分别已经拥有一个对象锁并且未解锁的情况下,互相请求获取对方的对象锁,就会造成死锁

例如:小明拿着玩具1,小红拿着玩具2,两人想要对方的玩具的同时,还不想放弃自己的玩具。两人就会僵持住(死锁)

生产者和消费者

wait()方法:this.wait,会释放锁,所以一般都是使用的同一个对象

notifyAll():通知所有wait的线程启动

线程池

放在其他地方

 

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!