• 1年之后的拿高工资的资本,Java线程


    只要开启线程,都会开启一块对应的栈内存,然后进行同步执行.    -- 谈斌

    线程是CPU用来处理程序的资源,线程的执行是抢占式的.

    线程开启方式:

    1. 创建一个类,继承Thread类.
      重写 run(), 并在run方法内编写线程需要执行的内容

      创建

      /*
       * 线程开启方式1:
       *   1.创建一个类,继承Thread类.
       *   2.重写 run(), 并在run方法内编写线程需要执行的内容
       * */
      public class MyThread extends Thread {
          // 构造方法
          public MyThread() {
              super();
          }
      
          public MyThread(String name) {
              super(name);
          }
      
          // run方法里面写的是线程需要执行的内容
          @Override
          public void run() {
              for (int i = 0; i < 100; i++) {
                  // 让线程睡2秒
                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e) { // 中途打断的意思
                      // 输出异常的 名称,信息,位置
                      e.printStackTrace();
                  }
                  System.out.println(getName()+"I Love Java");
              }
          }
      }
      /*
       * Runnable接口应该是被封装了开启cpu线程的C语言方法
       * */


      开启

      /*
       * 线程对象只能是
       *           Thread类的对象或者是Thread类的子类对象
       *
       * 线程体系结构:
       *           根节点: Runnable()接口 --> 抽象方法run()
       *           实现类: Thread类
       * 想在执行线程任务的时候,带上线程名称:
       *   String getName(): 获取线程名称
       *       --> 直接调用getName()方法只能在Thread的子类中调用
       *
       * 想在执行任务的时候打印主线程的名称:(因为ThreadDemo01类不是Thread的子类)
       * Thread类中有:
       *      static Thread currentThread():获取当前线程对象
       *      void setName(String name):对线程对象的名字进行设置
       *      static void sleep(long millis):让线程睡觉,睡多久: long millis决定
       * */
      public class ThreadDemo01 {
          public static void main(String[] args) throws InterruptedException {
              // 创建线程对象
              MyThread mt = new MyThread();
      
              // 启动线程
              mt.start(); // run方法是由start方法帮忙调用的
      
              for (int i = 0; i < 100; i++) {
                  Thread.sleep(3000);
                  System.out.println(Thread.currentThread().getName()+"I Love C^_^");
              }
          }
      }
    2.   (把任务和线程分离) --> 推荐
      创建一个类, 实现Runnable接口
      并在这个类中重写run(), 写入线程需要执行的任务

      创建

      /*
       * 第二种线程开启方式: (把任务和线程分离) --> 推荐
       *       1. 创建一个类, 实现Runnable接口
       *       2. 并在这个类中重写run(), 写入线程需要执行的任务
       * */
      public class Target implements Runnable {
          @Override
          public void run() {
              for (int i = 0; i < 50; i++) {
                  System.out.println(Thread.currentThread().getName() + ": Hello World !");
              }
          }
      }


      开启

      public class ThreadDemo02 {
          public static void main(String[] args) {
              // 创建线程的任务对象
              Target target = new Target();   // 任务
              Thread t0 = new Thread(target);  // 雇佣兵
              // 设置线程名称
              t0.setName("stark");
              t0.start();
      
              Thread t1 = new Thread(target);  // 另一个雇佣兵
              // 两个雇佣兵在做相同的任务
              t1.setName("spider");
              t1.start();
      
              // 匿名内部类开启线程方式,相当于开启方法一
              Thread t2 = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      for (int i = 0; i < 50; i++) {
                          System.out.println(Thread.currentThread().getName()+": biu biu biu~");
                      }
                  }
              });
              t2.setName("captain");
              t2.start();
          }
      }


      我并不明白匿名内部类开启线程的方式算不算一种新的开启方式,你觉得呢?

       

    线程安全问题 : 线程的抢占式执行机制, 造成了执行中出现的各种我们不想看到的问题.

      应对策略:   1.synchronized()

              2.Lock 锁

    /*
     * 同步代码块:
     *      synchronized(锁对象) {
     *          你需要上锁(同步)的代码
     *      }
     *      任意引用类型的对象,这个锁对象必须被所有的任务对象共享
     *
     *      总结:
     *          同步:当一个线程正在执行任务的时候,不让其他线程进入!!
     *          同步提高了代码的安全性,但是降低了代码的效率
     * */
    public class SellTicket  implements Runnable{
        // 成员变量
        int ticket = 100;
    
        /*
        * synchronized 里面可以放 Integer 却不能放 int 变量
        * 这也许就是包装类吧
        * */
        Integer tic = new Integer(ticket);
    
        // 锁对象 --> 你请人帮你看门
        Object obj = new Object();
    
        @Override
        public void run() {
            // 电影院不关门
            while (true) {
                synchronized (this) {// 你进了厕所把门关了
                    if (ticket > 0) {
                        // 每半秒钟卖一张票
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        // 窗口名 + “卖了第” +ticket+ “张票~”
                        System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~");
                        ticket--;
                    }
                }
            }
        }
    
        /*
        * 同步方法 --> 被 synchronized 修饰的方法
        *           锁对象 this
        *
        * 静态同步方法 --> 锁对象: 类的字节码对象!
        * */
    //    public synchronized void sell() {
    //        if (ticket > 0) {
    //            // 每半秒钟卖一张票
    //            try {
    //                Thread.sleep(500);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
    //            // 窗口名 + “卖了第” +ticket+ “张票~”
    //            System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~");
    //            ticket--;
    //        }
    //    }
    }
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /*
     * Lock 锁的使用步骤:
     *      1. 创建锁对象:
     *              Lock lock = new ReentrantLock();
     *      2. 在需要上锁的代码前面 上锁! --> lock.lock()
     * */
    public class SellTicket01 implements Runnable {
        // 成员变量
        int ticket = 100;
    
        /*
         * synchronized 里面可以放 Integer 却不能放 int 变量
         * 这也许就是包装类吧
         * */
        Integer tic = new Integer(ticket);
    
        // 创建锁对象
        Lock lock = new ReentrantLock();
    
        @Override
        public void run() {
            // 电影院不关门
            while (true) {
                lock.lock();
                if (ticket > 0) {
                    try {
                        // 每半秒钟卖一张票
                        Thread.sleep(500);
                        // 窗口名 + “卖了第” +ticket+ “张票~”
                        System.out.println(Thread.currentThread().getName() + "卖了第" + ticket + "张票~");
                        ticket--;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
    }

    最后附上线程的生老病死图, 希望大家月薪过万的时刻指日可待 ^^

     

  • 相关阅读:
    DB2数据库常用的函数总结
    word--->pdf资料转载..
    Spring boot -mongodb
    mongodb主从复制
    js-Math对象
    js-基本类型
    js-引用类型介绍
    js-检测数据类型
    javaScript计算对象的长度
    数据类型
  • 原文地址:https://www.cnblogs.com/nimoc/p/11470719.html
Copyright © 2020-2023  润新知