黑马程序员-day10-多线程上部分

------- android培训java培训、期待与您交流! ----------

进程 正在进行中的程序 每一个进程都有执行顺序,该顺序是一个执行路径,或者叫控制单元
线程 进程中的一个独立的控制单元,进程至少有一个线程 线程控制着进程的执行
多线程 一个进程中包含不止一个线程 比如玩英雄联盟,这是一个进程。其中包括打野线程和观察线上战况的线程。一边打野,一边观察线上的战况,此时大脑就是CPU,在打野和观察上频繁切换。
多线程一般用于执行循环结构;
jvm 进程java.exe 该进程中至少有一个主线程,并且该线程运行的代码存放在主函数中
Thread类 线程类 调用电脑系统方法创建线程
方法:run 新线程所要执行的代码,用来给子类复写
方法:getName 获取线程名称
方法:static Thread currentThread 返回当前线程(对象),静态的可直接类名调用
创建新线程方式1 第一步,创建类继承Thread 注意Thread的类中的方法和构造函数
第二步,类的构造方法,调取父类方法(可以自定义线程名称) 自定义线程名称,有默认的Thread-0、Thread-1…
第三步,复写Thread的run方法 run方法中,写入需要新线程执行的代码
创建该类的对象 创建新线程
对象名.start(); 执行新线程中的run方法
如果直接使用对象名.run();那么执行该方法的就不是新线程
创建新线程方式2 第一步,创建一个实现Runnable接口的类 如:class Demo extends Runnable
第二步,类中复写Runnable中的抽象方法 public void run()
Runnable中只有一个方法
第三步,新建一个该类对象 如:Demo d=new Demo()
第四步,新建一个线程类对象,将该类对象作为参数传给线程类的构造函数 如:Thread t=new Thread(d,name)
启动线程,调用run方法 如:t.start();
可用匿名内部类来写 Thread t=newThread(newRunnable()
  {
   privateint cola=50;
   publicvoid run()
   {
    //复写run方法的代码
   }
  },"线程1");
方式2优点1: 避免了java单继承的局限性,在实现Runnable的同时还可以继承其他类,
方式2优点2: 避免了创建静态变量,在继承方式中,由于线程对象不同,要使多个线程共享一个变量,就需要将该变量设置为static。但是在方式2中,由于是将实现Runnable类的同一个对象以参数形式传递给Thread的构造函数,因此不需要设置静态变量
多线程特性 随机性 多线程执行次序具有随机性,哪个线程抢到CPU执行权,谁执行,CPU在做着频繁切换,看起来似乎同时运行
多线程安全性 产生原因:多线程的随机性 当多个线程执行同一个方法,并且多个线程均使用到了该方法体中的共享数据时,如果此时方法体中不止一句代码,那么就有可能出现安全问题。比如if语句对共享数据判断,线程A判断满足后,执行权被B抢走,此时线程B判断时,仍然是满足。但是其实A如果正常执行完if语句中的代码,B再判断已经不满足了。此时就出现了安全问题
sleep方法 属于Thread类 public static sleep(long millis)throws InterruptedException
同步 前提 存在安全问题;操作共享数据的多个线程使用同一个锁
弊端 消耗资源
同步代码块
synchronized(任意非匿名对象)
哪些代码需要同步,看哪些代码操作了共享数据,再将这些代码写入同步代码块中
如果锁是匿名对象,当锁住后,匿名对象就变成垃圾了,那么每次进来,都是产生一个新的匿名对象,根本无法锁住(比如房间的锁,假设锁上后锁就自动消失了,这样的锁当然没用处了)
同步函数,在函数上加上synchronized修饰 函数内必须是全部操作共享数据的代码,如果还有其他代码,那么需要将需要同步的代码抽离出来,定义为另一个同步函数,再在该函数相应的地方,调用同步函数即可
找到需要同步的代码 1,找到多线程运行的代码。
2,明确这些代码的共享数据有哪些
3,明确多线程的代码中,有哪些是操作了共享数据的
synchronized(锁) 锁一般情况下是一个对象;
同步代码块的锁可是是任意一个非匿名对象;
同步函数的锁是本类对象,即this;
静态同步函数的锁是本类的class文件,即类名.class
死锁 同步嵌套并且使用的不是同一个锁 线程1拿到锁A,想要进锁B的时候,线程2刚好拿到锁B,想要进到锁A,导致程序卡死
需尽量避免死锁 面试时可能会考死锁

你可能感兴趣的:(java学习笔记)