[笔记] Java基础(8)-多线程

143 阅读5分钟

1. 并行与并发

  • 并行:多个任务同时执行
  • 并发:多个任务在一定时间内同时发生,轮流切换执行
  • Java程序运行流程:JVM进程->主线程->main方法

2. 多线程实现方式

  • 有两种方式,继承Thread类或实现Runnable接口
    • 继承Thread类:new Thread() { public void run() { ... } }.start();
    • 实现Runnable接口:new Thread( new Runnable() { public void run() { ... } }).start();
  • 区别:前者重写了Thread类的run方法,start方法直接调用子类的run方法;后者Thread中的成员变量赋值为传入的Runnable对象,start方法调用Threadrun方法,run方法内部判断Runnable成员变量是否为空,不为空则调用Runnable对象的run方法;后者弥补了前者单继承的不足

3. Thread类

  • Thread类:java.lang.Thread
  • Thread():创建新的Thread对象
  • Thread(String name):创建新的Thread对象,线程名为name
  • Thread(Runnable target):创建新的Thread对象
  • Thread(Runnable target, String name):创建新的Thread对象,线程名为name
  • String getName():获取线程名;主线程默认为main,子线程默认为Thread-x
  • long getId():获取线程id
  • void setName():设置线程名
  • static Thread currentThread():获取当前线程对象
  • static void sleep(long millis):让当前线程休眠指定的毫秒值
  • void setDeamen(boolean on):将线程设置为守护线程
    • 守护线程:当其它非守护线程执行完成后,守护线程自动退出
  • void join():等待该线程终止
  • void join(long millis):等待该线程执行指定的时间
  • static void yield():暂停当前线程,让CPU执行其它线程;效果不明显
  • void setPriority(int new):设置线程的优先级,范围1~10,默认为5;效果不明显

4. 线程同步

  • 同步代码块
    • 使用synchronized关键字修饰的代码块,如:synchronized(lock) { ... }
    • lock为锁对象,相同锁对象的代码块不能同时执行;锁对象不能使用匿名对象,因为匿名对象不是同一个对象
  • 同步方法
    • 在返回值前使用synchronized修饰的方法,分为静态方法与非静态方法
    • 非静态方法锁对象为this,如:public synchronized void fun() { ... }
    • 静态方法的锁对象为当前类的字节码对象,如:public static synchronized void fun() { ... }
  • 死锁DeadLock:多个线程同时抢占多个锁对象时,可能会产生死锁
    • 避免方法:同步代码块尽量不要嵌套使用
  • Collections工具类中有synchronizedXX()方法,可将ListSetMap变为线程安全的

5. Runtime类

  • Runtime类:java.lang.Runtime
  • 该类使用单例模式实现
  • static Runtime getRuntime():获取当前运行时对象
  • Process exec(String command):在单独的进程中执行指定命令

6. Timer类

  • Timer类:java.util.Timer
  • Timer():创建新的计时器对象
  • void schedule(TimeTask task, Date time):在指定的时间执行指定的任务;到指定的时间会调用task对象的run方法;TimeTask为抽象类
  • void schedule(TimeTask task, Date time, long period):在指定的时间执行指定的任务,然后按period的毫秒值重复执行
  • void cancel():终止计时器,丢弃所有任务

7. Object类

  • Object类中定义了线程等待与唤醒方法
  • void wait():当前线程等待,直到其他线程调用此对象的notify方法;wait在哪里进入等待,唤醒后就从哪里开始执行;wait对象直接使用锁对象
  • void notify():唤醒在此对象监视器上的单个线程
  • void notifyAll():唤醒在此对象监视器上的所有线程
  • sleepwait的区别:sleep在同步代码区域不会释放锁,wait会释放锁;sleep必须传入时间参数,wait可传可不传;sleep需要消耗CPU资源

8. ReentrantLock类

  • Reentrantlock类:java.util.concurrent.locks.ReentrantLock
  • 该类为JDK1.5之后加入
  • Reentrantlock():创建互斥锁对象
  • Codition newCondition():返回与该锁对象一起使用的Condition对象
    • Codition类:java.util.concurrent.locks.Condition
    • 该类与ReentrantLock类配合使用
    • void await():当前线程等待,直到其他线程调用signal方法
    • void signal():唤醒一个线程
    • void signalAll():唤醒所有线程
    • 该类的方法与Object类的waitnotify方法功能相似
    • 通过ReetrantLock对象的newCondition方法创建的Condition对象共同绑定同一个锁对象

9. ThreadGroup类

  • ThreadGroup类:java.lang.ThreadGroup
  • ThreadGroup(String name):创建新的线程组,名称为name
  • String getName():获取线程组的名称
  • void setDaemon(boolean daemon):设置组内线程的状态
  • 通过Thread对象的getThreadGroup方法可以获取该线程所属的线程组,默认线程都属于main线程组

10. 线程状态

  • 共有五种状态:新建、就绪、运行、阻塞、死亡
  • 新建:创建新的线程对象
    • 新建->就绪:start()
  • 就绪:有执行的资格,没有执行的权限
    • 就绪->运行:获取到CPU资源
  • 阻塞:没有执行的资格,没有执行的权限
    • 阻塞->就绪:获取到运行所需资源,除CPU
  • 运行:有执行的资格,有执行的权限
    • 运行->就绪:CPU资源被抢占
    • 运行->阻塞:sleep()wait()
    • 运行->死亡:run()执行完、stop()
  • 死亡:线程对象变成垃圾

11. 线程池

  • 线程池:包含多个线程,线程执行完后并不会死亡,而会进入空闲状态
  • Executors类:java.util.concurrent.Executors
  • 该类为JDK1.5之后加入;为工程类,用于创建线程池
  • static ExecutorService newFixedThreadPool(int nThreads):创建包含nThreads个线程的线程池
  • static ExecutorService newSingleThreadExecutor():创建包含一个线程的线程池
    • ExecutorService接口:java.util.concurrent.ExecutorService
    • Future<?> submit(Runnable task):提交task执行
    • void shutdown():关闭线程池,此时线程池不会接受新任务,以前的任务还会继续执行
    • Future<T> submit(Callable<T> task):提交有返回值的任务执行
      • 该方法会调用taskcall()方法
      • call()方法无参,故传参数需要使用构造方法
      • call()方法的返回值放在Future对象中,可以用get()方法获取
      • call()方法可以抛出异常