多线程笔记

作者: 白桦树97 | 来源:发表于2019-07-11 14:48 被阅读2次

    一:基础部分

    1. 并发与并行:
    - 并发 :同一个时间段内
    - 并行 :同一时刻
    
    1. 进程与线程:
    - 进程:内存中运行的一个应用程序
    - 线程: 一个进程中至少有一个线程
    
    image.png
    1. 线程调度:
    - 分时调度:所有线程轮流使用cpu的使用权
    - 抢占调度:(java) 优先级高的线程使用cpu
    
    1. Thread.sleep(); //静态方法 可直接使用
    2. 线程的实现方法:
    • 继承Thread类方法,@Override run方法
    • 实现Runnable接口 (避免单一继承,扩展性更高)
    1. 线程安全问题指的是: 对共享变量的修改。
    2. 线程启动方式。Thread thread = new Thread(r); //r为runable的实现类
    3. start() 是启动一个新线程,run()不启动
    4. wait(long) 如果在long时间内没有唤醒 则自己醒
    5. notify()随性唤醒一个线程
      notifyAll()唤醒所有的等待线程
    6. 线程通信:多个线程处理同共享资源时但是处理的动作不同,比如说一个吃包子,一个生产包子
    7. 线程池: 存有好多线程的集合,用的时候取,用完归还。

    二: 案例(卖票问题,三个窗口同时卖票)

    1. 不使用锁

    Ticket 类

    public class Ticket implements Runnable {
     private  Integer num = 100;
     @Override
     public void run() {
    
         while(true){
             if(num>0){
    //       Thread.sleep(100);  //使用休眠可使安全问题更加暴露
                 System.out.println(Thread.currentThread().getName()+" sell the "+num);
                 num--;
             }
         }
    
     }
    }
    
    

    测试类

    public class TicketTest {
     public static void main(String[] args) {
         Runnable run = new Ticket();
         Thread t1 = new Thread(run);
         Thread t2 = new Thread(run);
         Thread t3 = new Thread(run);
         t1.start();
         t2.start();
         t3.start();
    
     }
    }
    

    结果:出现了重复卖票,和卖不存在的票

    分析:当一个线程执行到if()时,当一个线程执行时,另一个线程也在执行这段代码,所以会出现问题。(加Thread可以让线程失去对cpu的执行权)

    二. 解决方案 (synchronized)

    1. synchronized 同步代码块
    2. synchronized 同步方法
    3. synchronized 静态方法

    使用同步方法

    public class Ticket implements Runnable {
        private  Integer num = 100;
    
        public synchronized void sell(){
            while(true){
                if(num>0){
    //                Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName()+" sell the "+num);
                    num--;
                }
            }
        }
        @Override
        public void run() {
            sell();
        }
    }
    

    三. 解决方案(Lock)

    public class Ticket implements Runnable {
        private  Integer num = 100;
        private Lock l = new ReentrantLock();
        @Override
        public void run() {
            while(true){
                l.lock();
                if(num>0){
    //                Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName()+" sell the "+num);
                    num--;
                }
                l.unlock();
            }
    
        }
    }
    
    

    三:线程的状态

    线程.png
    1. 线程通信->等待唤醒案例代码实现(synchronized同步代码块)
    public class DinnerTest {
        private Object obj = new Object();
        public static void main(String[] args) {
            Object obj = new Object();
            //顾客线程
            new Thread() {
                @Override
                public void run() {
                    synchronized (obj){
                        System.out.println("顾客点餐了");
                        try {
                            obj.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("顾客吃饭喽");
    
                    }
                }
            }.start();
    
            //厨师线程
            new Thread() {
                @Override
                public void run() {
                    synchronized (obj){
                        try {
                            Thread.sleep(3000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("厨师做饭完毕");
                        obj.notify();
                    }
                }
            }.start();
        }
    }
    

    四:线程池的实现

    
        public static void main(String[] args) {
            ExecutorService es = Executors.newFixedThreadPool(2);
            es.submit(new MyThread());
            es.submit(new MyThread());
            es.submit(new MyThread());
        }
    
    

    输出
    pool-1-thread-1正在执行
    pool-1-thread-2正在执行
    pool-1-thread-1正在执行

    线程池里只有两个线程,有三个任务,所以第三个任务会等待一个任务完成释放线程后再进行。

    相关文章

      网友评论

        本文标题:多线程笔记

        本文链接:https://www.haomeiwen.com/subject/kzvhkctx.html