H5W3
当前位置:H5W3 > 其他技术问题 > 正文

Java多线程基础

奋斗
There is no such thing as the end of success.

  • 什么是线程

    线程是进程内的执行单元

  • 线程的状态
    • NEW(初始状态)
    • RUNABLE(可运行状态)
      • BLOCKED(阻塞状态)
      • WAITNG(等待状态)
    • RUNNING(运行状态)
    • DEAD(死亡状态)
  • 创建一个线程

    1.重写Thread的Run方法

    new Thread(){
    @Override
    public void run() {
    System.out.println(1);
    }
    }.start();

    2.实现Runable接口

    new Thread(new Runnable() {
    @Override
    public void run() {
    System.out.println(1);
    }
    }).start();
  • 终止线程

    Thread.stop();不推荐使用,它会释放所有的monitor可以会导致多线程环境下数据不一致

    使用中断

    //当前线程没有收到中断信号时才工作
    while(Thread.cuurentThread().isInterrupted()){
    // do soming
    }
    // 发送中断信号
    t1.interrupt();
  • 中断线程

    public void Thread.interrupt();// 中断线程

    public boolean Thread.isInterrupt();// 判断是否被中断

    public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

  • 挂机(suspend)和继续执行(resume)
    • suspend() 不会释放锁
    • 如果加锁发生在resume()之前,则死锁发生
    		public static Object lock = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");
    public static class ChangeObjectThread extends Thread {
    public ChangeObjectThread(String name) {
    super.setName(name);
    }
    @Override
    public void run() {
    synchronized (lock) {
    System.out.println("in " + getName());
    Thread.currentThread().suspend();
    }
    }
    }
    public static void main(String[] args) throws InterruptedException {
    t1.start();
    Thread.sleep(1000);
    t2.start();
    t1.resume();
    t2.resume();
    t1.join();
    t2.join();
    }

    理论来说,线程t1,t2启动,挂起,然后继续执行,主函数应该会很快结束,但实际情况是 t1线程没问题正常结束,t2线程 由于通知继续执行的时候 还没有走到挂起代码,所以t2线程会一直处于挂起状态

  • 等待线程结束(join)和谦让(yeild)
    • public final void join() throws InterrptedException 等待线程执行完毕
    • public final synchronized void join(long millis) throws InterrptedException
    • public static void yeild() 暂时释放自己的执行权
  • 守护线程
    • 在后台默默地完成一些系统性的服务,比如垃圾回收线程,JIT线程就可以理解为守护线程
    • 当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出
    • 需要在线程启动之前进行设置
    public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread() {
    @Override
    public void run() {
    while(true){
    System.out.println("I am daemon Thread");
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    };
    thread.setDaemon(true);
    thread.start();
    Thread.sleep(1000);
    System.out.println("main thread end");
    }
  • 线程优先级

    高优先级的线程更容易再竞争中获胜

    • public final static int MIN_PRIORITY = 1;
    • public final static int NORM_PRIORITY = 5;
    • public final static int MAX_PRIORITY = 10;
    public static class HighPriority extends Thread {
    static int count = 0;
    @Override
    public void run() {
    while (true) {
    synchronized (PriorityDemo.class) {
    count++;
    if (count > 100000000) {
    System.out.println("HighPriority is complete");
    break;
    }
    }
    }
    }
    }
    public static class LowPriority extends Thread {
    static int count = 0;
    @Override
    public void run() {
    while (true) {
    synchronized (PriorityDemo.class) {
    count++;
    if (count > 100000000) {
    System.out.println("LowPriority is complete");
    break;
    }
    }
    }
    }
    }
    /**
    * 高优先级先完成的次数多,但是不保证
    * @param args
    */
    public static void main(String[] args) {
    Thread high = new HighPriority();
    Thread low = new LowPriority();
    high.setPriority(Thread.MAX_PRIORITY);
    low.setPriority(Thread.MIN_PRIORITY);
    low.start();
    high.start();
    }
  • 基本的线程同步操作
    • synchronized
      • 指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
      • 直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
      • 直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁

      加锁对象

      public class AccountingSync implements Runnable{
      static final AccountingSync instance = new AccountingSync();
      static int i = 0;
      @Override
      public void run() {
      for (int j = 0; j < 100000000; j++) {
      synchronized (instance){
      i++;
      }
      }
      }
      public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(instance);
      Thread t2 = new Thread(instance);
      t1.start();
      t2.start();
      t1.join();
      t2.join();
      System.out.println(i);
      }
      }

      加锁实例方法

      public class AccountingSync2 implements Runnable {
      static AccountingSync2 instance = new AccountingSync2();
      static int i = 0;
      public synchronized void increase() {
      i++;
      }
      @Override
      public void run() {
      for (int j = 0; j < 10000000; j++) {
      increase();
      }
      }
      public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(instance);
      Thread t2 = new Thread(instance);
      t1.start();
      t2.start();
      t1.join();
      t2.join();
      System.out.println(i);
      }
      }

      加锁实例方法,由于这个实例是new的两个实例导致获取的不是同一把锁

      public class AccountingSyncBad implements Runnable {
      static int i = 0;
      public synchronized void increase() {
      i++;
      }
      @Override
      public void run() {
      for (int j = 0; j < 10000000; j++) {
      increase();
      }
      }
      public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(new AccountingSyncBad());
      Thread t2 = new Thread(new AccountingSyncBad());
      t1.start();
      t2.start();
      t1.join();
      t2.join();
      System.out.println(i);
      }
      }

      加锁静态方法,类锁 会对AccountingSyncClass.class 进行加锁由于是同一把锁所以数据没问题

      public class AccountingSyncClass implements Runnable {
      static int i = 0;
      public  static synchronized void increase() {
      i++;
      }
      @Override
      public void run() {
      for (int j = 0; j < 10000000; j++) {
      increase();
      }
      }
      public static void main(String[] args) throws InterruptedException {
      Thread t1 = new Thread(new AccountingSyncClass());
      Thread t2 = new Thread(new AccountingSyncClass());
      t1.start();
      t2.start();
      t1.join();
      t2.join();
      System.out.println(i);
      }
      }
    • Object.wait()

      会使当前线程等待,必须拥有当前对象的锁,并且会释放当前对象的所有权,并等待其他线程通知当前线程继续执行

      Object object = new Object();
      synchronized (object){
      object.wait();
      }
    • Object.notify()

      唤醒一个等待在当前对象的线程锁,必须拥有当前对象的锁,wait的线程必须等待此同步块的代码完成后,在去竞争锁

      如果有多个线程的话 随机唤醒一个,notifyAll() 唤醒所有

      Object object = new Object();
      synchronized (object){
      object.notify();
      }
    • wait notify
      public static void main(String[] args) {
      final Object object = new Object();
      new Thread() {
      @Override
      public void run() {
      synchronized (object) {
      System.out.println(System.currentTimeMillis() + ":T1 start");
      try {
      object.wait();
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      System.out.println(System.currentTimeMillis() + ":T1 end");
      }
      }
      }.start();
      new Thread() {
      @Override
      public void run() {
      synchronized (object) {
      System.out.println(System.currentTimeMillis() + ":T2 start");
      object.notify();
      try {
      Thread.sleep(2000);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      System.out.println(System.currentTimeMillis() + ":T2 end");
      }
      }
      }.start();
      }

本文地址:H5W3 » Java多线程基础

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址