多线程基础

多线程基础

线程简介

  1. 线程

    CPU调度和执行的单位

  2. 进程

    系统资源分配的单位

  3. 多线程

    一般为CPU的个数

线程创建

  1. Thread---继承

    • 自定义线程类继承Thread类

    • 重写run()方法,编写线程执行体

    • 创建线程对象,调用start()方法进行调用

      public class TestThread extends Thread{
          @Override
          public void run() {
              //run方法
              for (int i = 0; i < 20; i++) {
                  System.out.println("测试多线程===");
              }
          }
      
          public static void main(String[] args) {
              TestThread testThread = new TestThread();
              testThread.start();
              for (int i = 0; i < 2000; i++) {
                  System.out.println("主线程====");
              }
          }
      }
      

      不建议使用:避免OOP单继承局限性

  2. Runnable--实现

    • 定义类实现Runnable接口

    • 实现run()方法,编写线程执行体

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

      public class TestThread2 implements Runnable {
          @Override
          public void run() {
              for (int i = 0; i < 20; i++) {
                  System.out.println("测试多线程===");
              }
          }
      
          public static void main(String[] args) {
              TestThread2 testThread2 = new TestThread2();
              //实现方法1
              Thread thread = new Thread(testThread2);
              thread.start();
              //实现方法2
              new Thread(testThread2).start();
      
              for (int i = 0; i < 2000; i++) {
                  System.out.println("主线程===");
              }
          }
      }
      
      

      推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用

  3. Callable---实现

    • 实现Callable接口,需要返回值类型

    • 重写call方法,需要抛出异常

    • 创建目标对象

    • 创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);

    • 提交执行:Future<Boolean> result = ser.submit(t1);

    • 获取结果:boolean r1 = result.get();

    • 关闭服务:ser.shutdownNow()

      import java.util.concurrent.*;
      
      public class TestThread4 implements Callable<Boolean> {
          @Override
          public Boolean call() throws Exception {
              System.out.println("--->多线程: " + Thread.currentThread().getName());
              return true;
          }
      
      
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              TestThread4 t1 = new TestThread4();
              TestThread4 t2 = new TestThread4();
              TestThread4 t3 = new TestThread4();
              //开启固定线程池
              ExecutorService service = Executors.newFixedThreadPool(3);
              //提交线程
              Future<Boolean> r1 = service.submit(t1);
              Future<Boolean> r2 = service.submit(t2);
              Future<Boolean> r3 = service.submit(t3);
              //获取结果
              boolean rs1 = r1.get();
              boolean rs2 = r2.get();
              boolean rs3 = r3.get();
              //关闭线程池
              service.shutdownNow();
          }
      }
      

静态代理---线程底层原理

  • 真实对象和代理对象实现同一个接口
  • 代理对象代理真实对象
  • 好处:真实对象做自己的事情,代理对象做一些额外的事情

Lambda表达式

  • 外部类

  • 静态内部类

  • 局部内部类

  • 匿名内部类

  • lambda表达式

    public class TestLambda {
        //2.静态内部类
        static class Like2 implements Ilike {
            @Override
            public void lambda() {
                System.out.println("test lambda2");
            }
        }
    
        public static void main(String[] args) {
            Ilike ilike = new Like();
            ilike.lambda();
    
            ilike = new Like2();
            ilike.lambda();
            //3.局部内部类
            class Like3 implements Ilike {
                @Override
                public void lambda() {
                    System.out.println("test lambda3");
                }
            }
            ilike = new Like3();
            ilike.lambda();
    
            //4.匿名内部类,没有类的名称,必须借助接口或者父类
            ilike = new Ilike() {
                @Override
                public void lambda() {
                    System.out.println("test lambda4");
                }
            };
            ilike.lambda();
    
            //5.lambda表达式
            ilike = () -> {
                System.out.println("test lambda5");
            };
            ilike.lambda();
        }
    }
    
    //定义抽象接口
    interface Ilike {
        void lambda();
    }
    //1.定义外部类
    class Like implements Ilike {
    
        @Override
        public void lambda() {
            System.out.println("test lambda1");
        }
    }
    

线程状态

  • 创建状态

    • new Thread进入创建状态
  • 就绪状态

    • 调用start()方法进入就绪状态,并不是立刻调度执行
  • 阻塞状态

    • 线程调用sleepwait或者同步锁定时,线程进行阻塞状态
  • 运行状态

    • 线程真正执行,就绪状态调度
  • 死亡状态

    • 线程中断或者结束,进入死亡状态
  • 方法

    • 停止线程:定义标志位让线程停止

      public class TestStop implements Runnable {
          private boolean flag = true;
          @Override
          public void run() {
              int i = 0;
              while (flag) {
                  System.out.println("run...Thread" + i++);
              }
          }
      
          public void stop() {
              this.flag = false;
          }
      
          public static void main(String[] args) {
              TestStop testStop = new TestStop();
      
              new Thread(testStop).start();
      
              for (int i = 0; i < 1000; i++) {
                  System.out.println("main" + i);
                  if (i == 900) {
                      testStop.stop();
                      System.out.println("线程停止");
                  }
              }
          }
      }
      
      
    • 线程休眠

      • sleep不会释放锁
    • 线程让步

      • 线程让步不一定成功,CPU重新调度
    • 线程join

      • 合并线程,线程执行完毕,在执行其它线程

        public class TestJoin implements Runnable {
            @Override
            public void run() {
                for (int i = 0; i < 1000; i++) {
                    System.out.println("join线程" + i);
                }
            }
        
            public static void main(String[] args) throws InterruptedException {
                TestJoin testJoin = new TestJoin();
        
                Thread thread = new Thread(testJoin);
        
                thread.start();
        
                for (int i = 0; i < 500; i++) {
                    if (i == 200) {
                        thread.join();
                    }
                    System.out.println("main" + i);
                }
            }
        }
        
        
    • 线程状态获取

      • Thread.State

        import javax.swing.plaf.TableHeaderUI;
        
        public class TestState {
        
            public static void main(String[] args) throws InterruptedException {
                Thread thread = new Thread(() -> {
                    for (int i = 0; i < 5; i++) {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("---------");
                });
                Thread.State state = thread.getState();
                System.out.println(state);
        
                thread.start();
                state = thread.getState();
                System.out.println(state);
        
                while (state != Thread.State.TERMINATED) {
                    Thread.sleep(1000);
                    state = thread.getState();
                    System.out.println(state);
                }
            }
        }
        
        
    • 线程优先级

      • 最小为1,最大为10
      • 优先级高并不会一定最先运行
  • 守护线程

    • 用户线程默认
    • 守护线程--需要设置,gc就是守护线程

线程同步

  • 定义:一个对象被多个线程同时操作

  • 形成条件:队列和锁

  • 同步方法:synchronized关键字--默认锁this,锁的对象是变化的量

  • 死锁:多个线程拿到对方需要的资源

  • Lock类:ReentrantLock(可重入锁)

    class A {
        private final ReentrantLock lock = new ReentrantLock();
        
        public void run() {
            lock.lock();
            try {
                //线程安全的代码
            } finally {
                //将解锁放入finally代码块,防止线程安全的代码出现异常,一直持有锁
                lock.unlock();
            }
        }
    }
    
  • Lock和synchronized对比

    • Lock是显式锁(手动开启关闭锁),synchronized是隐式锁,脱离作用域自动释放锁
    • Lock只有代码块锁,synchronized有代码块和方法锁
    • 使用Lock锁,JVM花费少的时间进行调度
    • 使用顺序:Lock > 同步代码块 > 同步方法

线程通信问题

  • 线程通信

    • wait() 等待其他线程通知,释放锁
    • wait(long timeout) 指定等待时间释放锁
    • notify() 唤醒一个处于等待状态的线程
    • notifyAll() 唤醒所有等待状态的线程
    • 以上方法均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIegalMonitorStateException
  • 管程法

    //生产者消费者模型---利用缓冲区:管程法
    //生产者,消费者,产品,缓冲区
    
    public class TestPC {
        public static void main(String[] args) {
            SynContainer  container = new SynContainer();
    
            new Productor(container).start();
            new Consumer(container).start();
        }
    }
    //生产者
    class Productor extends Thread {
        SynContainer container;
    
        public Productor(SynContainer container) {
            this.container = container;
        }
    
        //生产
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                container.push(new Product(i));
                System.out.println("生产了" + i + "个产品");
            }
        }
    }
    //消费者
    class Consumer extends  Thread {
        SynContainer container;
    
        public Consumer(SynContainer container) {
            this.container = container;
        }
        //消费
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.println("消费了--> " + container.pop().id + "个产品");
            }
        }
    }
    
    class Product {
        int id;
        public Product(int id) {
            this.id = id;
        }
    }
    
    class SynContainer {
        //需要一个容器大小
        Product[] products = new Product[100];
        //容器计数器
        private int count = 0;
    
        public synchronized void push(Product product) {
            //如果容器满了,需要等待消费者消费
            if (count == products.length) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //如果没有满,放入产品
            products[count] = product;
            count++;
    
            //通知消费者消费
            this.notifyAll();
        }
    
        public synchronized Product pop() {
            //判断是否能够消费
            if (count == 0) {
                //等待生产者生产,消费者等待
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //可以消费
            count--;
            Product product = products[count];
            //通知生产者生产
            this.notifyAll();
            return product;
        }
    }
    
  • 信号灯法

    public class TestPC2 {
        public static void main(String[] args) {
            Program program = new Program();
    
            new Player(program).start();
            new Watcher(program).start();
        }
    }
    //生产者->演员
    class Player extends Thread {
        Program program;
        public Player(Program program) {
            this.program = program;
        }
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                if (i % 2 == 0) {
                    this.program.play("少年包青天");
                } else {
                    this.program.play("广告");
                }
            }
        }
    }
    
    //消费者->观众
    class Watcher extends Thread {
        Program program;
        public Watcher(Program program) {
            this.program = program;
        }
        @Override
        public void run() {
            for (int i = 0; i < 20; i++) {
                program.watch();
            }
        }
    }
    
    //节目
    class Program {
        //表演的节目
        String voice;
        //演员表演为true,观众观看为false
        boolean flag = true;
    
        //表演
        public synchronized void play(String voice) {
            if (!flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("演员表演了:" + voice);
            this.notifyAll();
            this.voice = voice;
            this.flag = !this.flag;
        }
    
        //观看
        public synchronized void watch() {
            if (flag) {
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("观众观看了:" + voice);
            this.notifyAll();
            this.flag = !this.flag;
        }
    
    }
    

高级主题

  • 线程池

    • ExecutorService

      • void excute(Runnable command) 执行任务,没有返回值

      • <T> Future<T> submit(Callable<T> task) 执行任务,有返回值

      • void shutdown() 关闭连接池

        import java.util.concurrent.Executor;
        import java.util.concurrent.ExecutorService;
        import java.util.concurrent.Executors;
        
        public class TestPool {
            public static void main(String[] args) {
                //创建线程池
                ExecutorService service = Executors.newFixedThreadPool(10);
        
                service.execute(new MyThread());
                service.execute(new MyThread());
                service.execute(new MyThread());
                service.execute(new MyThread());
        
                service.shutdown();
            }
        }
        
        class MyThread implements Runnable {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }
        
        
posted @ 2021-01-17 16:21  学徒之心  阅读(43)  评论(0编辑  收藏  举报