ITPub博客

首页 > 大数据 > 数据挖掘 > 好程序员大数据学习路线分享大数据之线程

好程序员大数据学习路线分享大数据之线程

原创 数据挖掘 作者:好程序员IT 时间:2019-09-25 16:26:49 0 删除 编辑

  好程序员大数据学习路线分享大数据之线程, 默认情况下, 主线程和垃圾回收线程都是由系统创建的 , 但是我们需要完成自己的功能 ---- 创建自己的线程对象

 

 java 将线程面向对象了 , 形成的类就是 Thread, 在 Thread 类内部执行任务的方法叫 run()

  注意: 如果想让 run 作为任务区 , 必须让他去被自动调用 . 我们通过执行 start() 方法 , 来开启线程 , 继而实现 run 方法的自动调用 .

主线程的名字:main    子线程的名字 : 从 Thread-0 开始命名

 

// 创建自己的线程对象

// 分析 : 由于我们实现的实际功能 Thread 类是决定不了的 , 所以没有办法将我们的功能放入 Thread 的 run 方法里,如果我们想实现自己的功能 , 可以写 Thread 类的子类 , 重写 run 方法 , 实现我们的功能 .run 就是我们的任务区

 

实现多线程的方式两种:

  第一种方式: 通过创建 Thread 子类的方式实现功能 ---- 线程与任务绑定在了一起 , 操作不方便

  第二种: 将任务从线程中分离出来 , 哪个线程需要工作 , 就将任务交给谁 , 操作方便

当线程与任务分离后

这里Thread 内部默认有一个 run, 又通过 ticket 传入一个 run, 为什么优先调用的是传入的 run

如果该线程是使用独立的 Runnable  运行对象构造的,则调用该  Runnable  对象的  run  方法;否则,该方法不执行任何操作并返回。

 

2. 线程安全

1 、 synchronized 关键字:

1 、 synchronized 关键字的作用域有二种:

1 )是某个对象实例内, synchronized aMethod(){} 可以防止多个线程同时访问这个对象的 synchronized 方法(如果一个对象有多个 synchronized 方法,只要一个线程访问了其中的一个 synchronized 方法,其它线程不能同时访问这个对象中任何一个 synchronized 方法)。这时,不同的对象实例的 synchronized 方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的 synchronized 方法;

2 )是某个类的范围, synchronized static aStaticMethod{} 防止多个线程同时访问这个类中的 synchronized static  方法。它可以对类的所有对象实例起作用。

2 、除了方法前用 synchronized 关键字, synchronized 关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是 : synchronized(this){/ 区块 /} ,它的作用域是当前对象;

3 、 synchronized 关键字是不能继承的,也就是说,基类的方法 synchronized f(){}  在继承类中并不自动是 synchronized f(){} ,而是变成了 f(){} 。继承类需要你显式的指定它的某个方法为 synchronized 方法;

 

 

实现线程安全的方式:

1. 在代码中使用同步代码块儿 ( 同步锁 )

解释: 在某一段任务中 , 同一时间只允许一个线程执行任务 , 其他的线程即使抢到了 cpu, 也无法进入当前的任务区间 , 只有当当前的线程将任务执行完后 , 其他的线程才能有资格进入

同步代码块儿的构成:

synchronized( 锁 ( 对象 )){

   同步的代码

 }

对作为锁的对象的要求:

1. 必须是对象      

2. 必须保证被多个线程共享

可以充当锁的:

1. 一个普通的对象      

2. 当前对象的引用 --this    

3. 类的字节码文件  -- 注意 : 字节码文件的使用范围太大 , 一般不建议使用 .

同步代码块儿的特点:

1. 可以保证线程的安全    

2. 由于每次都要进行判断处理 , 所以降低了执行效率

总结: 什么时候使用同步代码块儿

1. 多个线程共享一个数据

2. 至少有两个线程

 

比较同步代码块儿和同步函数

同步代码块儿使用更加的灵活, 只给需要同步的部分代码同步即可 , 而同步函数是给这个函数内的所有代码同步 .

由于处于同步的代码越少越好, 所以最好使用同步代码块儿

注意:1. 当在一个类中同时存在多个 synchronized 修饰的代码块儿或函数时,要想安全,就必须让他们后面的对象一致。因为只有同一把锁才能安全。

同步函数的锁:this

2 静态同步函数在进内存的时候不会创建对象,但是存在其所属类的字节码文件对象,属于 class 类型的对象,

所以静态同步函数的锁是其所属类的字节码文件对象

 

示例:

    //使用同步代码块儿

    public void addMoney(int money) {

        synchronized (Bank.class) {

            this.money += money;

            System.out.println(this.money);

        }

    }

    //使用同步函数

    //非静态的同步函数

    //在synchronized后面默认有一个this

    public synchronized void addMoney(int money) {

        this.money += money;

        System.out.println(this.money);

    }

 

 wait(): 让当前的线程变成等待的状态 , 放入一个池子 ( 线程容器 ), 失去了抢 cpu 的能力 ,. 等待唤醒 ( 锁相当于给当前的线程做了一个标记 )

notify(): 让当前的线程从等待状态唤醒 , 相当于从池子中取出线程 .( 唤醒的是同一把锁下的任意一个线程 )

notifyAll(): 唤醒的是同一把锁下的所有线程

 

死锁: 出现的情况有两种

 1. 所有的线程处于等待状态

 2. 锁之间进行嵌套调用

 

2.Lock

比较synchronized 和 Lock

 1.synchronized: 从 jdk1.0 就开始使用的同步方法 - 称为隐式同步

 synchronized( 锁对象 ){// 获取锁      我们将锁还可以称为锁旗舰或者监听器

  同步的代码

 }// 释放锁

 2.Lock: 从 jdk1.5 开始使用的同步方法 - 称为显示同步

  原理:Lock 本身是接口 , 要通过他的子类创建对象干活儿

  使用过程:

  首先调用lock() 方法获取锁

  进行同步的代码块儿

  使用unlock() 方法释放锁

  使用的场景:

  当进行多生产者多消费者的功能时, 使用 Lock, 其他的都使用 synchronized

  使用效率上:Lock 高于 synchronized

 

线程的停止: 3 种

 1. 通过一个标识结束线程

 2. 调用 stop 方法 --- 因为有固有的安全问题 , 所以系统不建议使用 .

 3. 调用 interrupt 方法 ---- 如果目标线程等待很长时间(例如基于一个条件变量),则应使用  interrupt  方法来中断该等待。

 

守护线程:

相当于后台线程. 依赖于前台线程 . 正常情况下 , 当前台线程结束的时候 , 不管守护线程有没有结束 , 都会立刻结束 .

  典型的守护线程: 垃圾回收线程

  当程序调用setDaemon 方法时 , 并且将参数设置成 true. 当前线程就变成了守护线层 .

  注意: 这个方法一定要在 start 方法之前调用

 thread0.setDaemon(true);

 thread0.start();

 

join() 方法 :

 

  原理: 线程一旦调用了 join 方法 , 他的优先级会高于主线程 . 主线程会等当前的线程执行完后再去执行 .

  注意点: 优先级只比 main 线程的高 . 对其他的线程没有影响 .

  当线程开始工作后, 让 t0 调用 join 方法 , 让他的优先级高于 main 线程

  注意:join 方法必须在线程开始工作后 , 执行 .

     t0.start();
      try {
          t0.join();
      } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

wait(): 使一个线程处于等待状态,并且释放所持有的对象的 lock 。

sleep(): 使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉 InterruptedException 异常。

notify(): 唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由 JVM 确定唤醒哪个线程,而且不是按优先级。

notityAll(): 唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。

 


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69913892/viewspace-2658230/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
欢迎关注公众号:好程序员特训营 web前端教程分享 723729549 大数据教程分享 703503210

注册时间:2019-03-20

  • 博文量
    539
  • 访问量
    410781