想了解线程,必须先了解进程,因为线程是依赖进程存在的。

什么是进程?
进程就是正在运行的程序;是系统进行资源分配和调用的独立单位。每一个进程都有它自己的内存空间和系统资源。

多进程有什么意义?
单进程的计算机只能做一件事情,而我们现在的计算机可以做多件事情。
举例:一边玩游戏,一边听音乐等
现在的计算机都支持多进程的,可以在一个时间段内执行多个任务。并且,可以提高CPU使用率。

什么是线程?
在同一个进程内又可以执行多个任务,而每一个任务可以看成是一个线程。
线程:是程序的执行单元,执行路径。是程序使用CPU的最基本单位。
单线程:如果程序只有一条执行路径。
多线程:如果程序有多条执行路径。

多线程有什么意义呢?
多线程的存在,不是提高程序的执行速度。其实是为了提高应用程序的使用率。
程序的执行其实都是在抢CPU的资源,CPU的执行权。
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的机率抢到CPU的执行权。
我们不敢保证哪一个线程能够在哪个时刻抢到,所以线程执行有随机性。

并行和并发的区别:
并行:是逻辑上同时发生,指在某一个时间内同时运行多个程序。
并发:是物理上同时发生,指在某一个时间点同时运行多个程序。

Java程序的运行原理:
由java命令启动JVM,JVM启动就相当于启动一个进程。
接着有该进程创建了一个主线程去调main方法。

方法1:继承Thread实现线程
步骤:
A:自定义类MyThread继承Thread类
B:MyThread类里面重写run()
C:创建对象
D:启动线程

该类为什么重写run()方法? 不是类中所有代码都需要被线程执行的。而这个时候,为了区分哪些代码能够被线程执行,Java提供了run方法来包含被线程执行的代码。

public class MyThread extends Thread {

 @Override    public void run() {       // 一般来说,被线程执行的代码肯定是比较耗时的。                     // 所以我们用循环改进       for (int x = 0; x < 200; x++) {         System.out.println(x);        } }

}

public class MyThreadDemo { public static void main(String[] args) {      // 创建线程对象     // MyThread my = new MyThread();     // // 启动线程        // my.run();      // my.run();      // 调用run()方法为什么是单线程的呢?        // 因为run()方法直接调用其实就相当于普通的方法调用,所以你看到的是单线程的效果       // 要想看到多线程的效果,就必须说说另一个方法:start()        // 面试题:run()和start()的区别?       // run():仅仅是封装被线程执行的代码,直接调用是普通方法       // start():首先启动了线程,然后再由jvm去调用该线程的run()方法。      // MyThread my = new MyThread();     // my.start();        // // IllegalThreadStateException:非法的线程状态异常       // // 为什么呢?因为这个相当于是my线程被调用了两次。而不是两个线程启动。      // my.start();

      // 创建两个线程对象       MyThread my1 = new MyThread();       MyThread my2 = new MyThread();

     my1.start();      my2.start();  }}

获取线程对象的名称:
public final String getName() :获取线程对象的名称

设置线程对象的名称:
public final void setName()

针对不是Thread类的子类中如何获取线程对象名称
public static Thread currentThread() : 返回当前正在执行的线程对象
Thread.currentThread().getName()

public class MyThreadDemo {  public static void main(String[] args) {      // 创建线程对象     //无参构造+setXxx()      // MyThread my1 = new MyThread();        // MyThread my2 = new MyThread();        // //调用方法设置名称     // my1.setName("林青霞");      // my2.setName("刘意");       // my1.start();       // my2.start();

     //带参构造方法给线程起名字        // MyThread my1 = new MyThread("林青霞");     // MyThread my2 = new MyThread("刘意");      // my1.start();       // my2.start();

     //我要获取main方法所在的线程对象的名称,该怎么办呢?      //遇到这种情况,Thread类提供了一个很好玩的方法:      //public static Thread currentThread():返回当前正在执行的线程对象      System.out.println(Thread.currentThread().getName()); }}

public final void setDaemon(boolean on)将线程设置为守护线程或用户线程
当正在运行的线程都是守护线程时,Java虚拟机退出, 该方法必须在启动前调用

public class ThreadDaemon extends Thread {   @Override    public void run() {       for (int x = 0; x < 100; x++) {         System.out.println(getName() + ":" + x);      } }}

public class ThreadDaemonDemo {   public static void main(String[] args) {      ThreadDaemon td1 = new ThreadDaemon();       ThreadDaemon td2 = new ThreadDaemon();

     td1.setName("关羽");      td2.setName("张飞");

        // 设置守护线程     td1.setDaemon(true);      td2.setDaemon(true);

        td1.start();      td2.start();

        Thread.currentThread().setName("刘备");       for (int x = 0; x < 5; x++) {           System.out.println(Thread.currentThread().getName() + ":" + x);       } }}

public final void join() ; 等待该线程终止后再调用其它线程

public class ThreadJoinDemo {    public static void main(String[] args) {      ThreadJoin tj1 = new ThreadJoin();       ThreadJoin tj2 = new ThreadJoin();       ThreadJoin tj3 = new ThreadJoin();

     tj1.setName("李渊");      tj2.setName("李世民");     tj3.setName("李元霸");

       tj1.start();      try {         tj1.join();       } catch (InterruptedException e) {            e.printStackTrace();      }

       tj2.start();      tj3.start();  }}

设置线程对象优先级
public final int getPriority() :返回线程对象优先级
public final void setPriority(int ne) : 设置线程优先级

注意:
线程默认优先级是5
线程优先级的范围是 : 1-10
线程优先级高仅表示线程获取的CPU时间片的几率高,需要在次数比较多,或多次运行时效果才比较显著。

IllegalArgumentException:非法参数异常。
抛出的异常表明向方法传递了一个不合法或不正确的参数。

public class ThreadPriority extends Thread { @Override    public void run() {       for (int x = 0; x < 100; x++) {         System.out.println(getName() + ":" + x);      } }}

public class ThreadPriorityDemo {   public static void main(String[] args) {      ThreadPriority tp1 = new ThreadPriority();       ThreadPriority tp2 = new ThreadPriority();       ThreadPriority tp3 = new ThreadPriority();

     tp1.setName("东方不败");        tp2.setName("岳不群");     tp3.setName("林平之");

       // 获取默认优先级        // System.out.println(tp1.getPriority());     // System.out.println(tp2.getPriority());     // System.out.println(tp3.getPriority());

       // 设置线程优先级        // tp1.setPriority(100000);

     //设置正确的线程优先级      tp1.setPriority(10);      tp2.setPriority(1);

     tp1.start();      tp2.start();      tp3.start();  }}

public static void sleep() 线程休眠

public class ThreadSleep extends Thread {    @Override    public void run() {       for (int x = 0; x < 100; x++) {         System.out.println(getName() + ":" + x + ",日期:" + new Date());         // 睡眠         // 困了,我稍微休息1秒钟         try {             Thread.sleep(1000);           } catch (InterruptedException e) {                e.printStackTrace();          }     } }}

public class ThreadSleepDemo {    public static void main(String[] args) {      ThreadSleep ts1 = new ThreadSleep();     ThreadSleep ts2 = new ThreadSleep();     ThreadSleep ts3 = new ThreadSleep();

       ts1.setName("林青霞");     ts2.setName("林志玲");     ts3.setName("林志颖");

       ts1.start();      ts2.start();      ts3.start();  }}

线程中断
public final void stop() : 让线程停止,过时了, 超过一定时间,直接结束进程
public final void interrupt() : 中断线程,把线程的状态终止,并抛出一个InterruptedException。

public class ThreadStop extends Thread { @Override    public void run() {       System.out.println("开始执行:" + new Date());

     // 我要休息10秒钟,亲,不要打扰我哦        try {         Thread.sleep(10000);      } catch (InterruptedException e) {            // e.printStackTrace();           System.out.println("线程被终止了");       }

       System.out.println("结束执行:" + new Date());   }}

public class ThreadStopDemo { public static void main(String[] args) {      ThreadStop ts = new ThreadStop();        ts.start();

     // 你超过三秒不醒过来,      try {         Thread.sleep(3000);           // ts.stop();   // 结束线程           ts.interrupt(); //抛出异常,将线程状态终止     } catch (InterruptedException e) {            e.printStackTrace();      } }}

public static void yield() : 暂停当前正在执行的线程,让CPU去执行其它线程
让多个线程执行更和谐

public class ThreadYield extends Thread {    @Override    public void run() {       for (int x = 0; x < 100; x++) {         System.out.println(getName() + ":" + x);          Thread.yield();       } }}

public class ThreadYieldDemo {    public static void main(String[] args) {      ThreadYield ty1 = new ThreadYield();     ThreadYield ty2 = new ThreadYield();

       ty1.setName("林青霞");     ty2.setName("刘意");

        ty1.start();      ty2.start();  }}

方法二: 实现Runnable接口
步骤 : A:自定义MyRunnable实现Runnable接口
B:重写run()方法
C:创建MyRunnable类的对象
D:创建Thread类的对象,并把c步骤的对象作为构造参数传递

public class MyRunnable implements Runnable {

  @Override    public void run() {       for (int x = 0; x < 100; x++) {         // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用          System.out.println(Thread.currentThread().getName() + ":" + x);       } }

}

public class MyRunnableDemo {   public static void main(String[] args) {      // 创建MyRunnable类的对象       MyRunnable my = new MyRunnable();

      // 创建Thread类的对象,并把C步骤的对象作为构造参数传递       // Thread(Runnable target)        // Thread t1 = new Thread(my);       // Thread t2 = new Thread(my);       // t1.setName("林青霞");       // t2.setName("刘意");

      // Thread(Runnable target, String name)       Thread t1 = new Thread(my, "林青霞");     Thread t2 = new Thread(my, "刘意");

        t1.start();       t2.start();   }}

案例:模拟售票

版本1 : 继承Thread类

public class SellTicket extends Thread {

   // 定义100张票    // private int tickets = 100;    // 为了让多个线程对象共享这100张票,我们其实应该用静态修饰   private static int tickets = 100;

  @Override    public void run() {       // 定义100张票        // 每个线程进来都会走这里,这样的话,每个线程对象相当于买的是自己的那100张票,这不合理,所以应该定义到外面      // int tickets = 100;

      // 是为了模拟一直有票      while (true) {            if (tickets > 0) {             System.out.println(getName() + "正在出售第" + (tickets--) + "张票");          }     } }}

public class SellTicketDemo { public static void main(String[] args) {      // 创建三个线程对象       SellTicket st1 = new SellTicket();       SellTicket st2 = new SellTicket();       SellTicket st3 = new SellTicket();

     // 给线程对象起名字       st1.setName("窗口1");     st2.setName("窗口2");     st3.setName("窗口3");

       // 启动线程       st1.start();      st2.start();      st3.start();  }}

版本二: 实现Runnable接口

public class SellTicket implements Runnable {    // 定义100张票    private int tickets = 100;

 @Override    public void run() {       while (true) {            if (tickets > 0) {             System.out.println(Thread.currentThread().getName() + "正在出售第"                      + (tickets--) + "张票");            }     } }}

public class SellTicketDemo { public static void main(String[] args) {      // 创建资源对象     SellTicket st = new SellTicket();

      // 创建三个线程对象       Thread t1 = new Thread(st, "窗口1");     Thread t2 = new Thread(st, "窗口2");     Thread t3 = new Thread(st, "窗口3");

       // 启动线程       t1.start();       t2.start();       t3.start();   }}

版本三:通过sleep() 暴露出问题

public class SellTicket implements Runnable {    // 定义100张票    private int tickets = 100;

//   @Override//  public void run() {//     while (true) {//          // t1,t2,t3三个线程//         // 这一次的tickets = 100;//          if (tickets > 0) {//               // 为了模拟更真实的场景,我们稍作休息//             try {//                   Thread.sleep(100); // t1就稍作休息,t2就稍作休息//               } catch (InterruptedException e) {//                  e.printStackTrace();//                }////               System.out.println(Thread.currentThread().getName() + "正在出售第"//                        + (tickets--) + "张票");//              // 理想状态://             // 窗口1正在出售第100张票//                // 窗口2正在出售第99张票//             // 但是呢?//             // CPU的每一次执行必须是一个原子性(最简单基本的)的操作。//                // 先记录以前的值//              // 接着把ticket--//              // 然后输出以前的值(t2来了)//               // ticket的值就变成了99//               // 窗口1正在出售第100张票//                // 窗口2正在出售第100张票////            }//       }//   }

   @Override    public void run() {       while (true) {            // t1,t2,t3三个线程           // 这一次的tickets = 1;          if (tickets > 0) {             // 为了模拟更真实的场景,我们稍作休息               try {                 Thread.sleep(100); //t1进来了并休息,t2进来了并休息,t3进来了并休息,             } catch (InterruptedException e) {                    e.printStackTrace();              }

               System.out.println(Thread.currentThread().getName() + "正在出售第"                      + (tickets--) + "张票");                //窗口1正在出售第1张票,tickets=0              //窗口2正在出售第0张票,tickets=-1             //窗口3正在出售第-1张票,tickets=-2            }     } }}

/* * 实现Runnable接口的方式实现 *  * 通过加入延迟后,就产生了连个问题: * A:相同的票卖了多次 *        CPU的一次操作必须是原子性的 * B:出现了负数票 *        随机性和延迟导致的 */public class SellTicketDemo { public static void main(String[] args) {      // 创建资源对象     SellTicket st = new SellTicket();

      // 创建三个线程对象       Thread t1 = new Thread(st, "窗口1");     Thread t2 = new Thread(st, "窗口2");     Thread t3 = new Thread(st, "窗口3");

       // 启动线程       t1.start();       t2.start();       t3.start();   }}

如何解决线程安全问题?
分析哪些原因导致问题:
A: 是否是多线程环境
B: 是否共享数据
C: 是否有多条语句操作共享数据

解决思路:
把多条语句操作共享数据的代码给包成一个整体,让某一个线程在执行的时候,别的线程不能进入。
同步代码块:
synchronized(对象){
需要同步的代码
}
注意: 同步可以解决安全问题的根本原因就在那个对象上,该对象如同锁的功能。
多个线程必须是同一把锁。

版本四:使用synchronized 同步解决问题

public class SellTicket implements Runnable {    // 定义100张票    private int tickets = 100;   //创建锁对象   private Object obj = new Object();

//   @Override//  public void run() {//     while (true) {//          synchronized(new Object()){//             if (tickets > 0) {//                   try {//                       Thread.sleep(100); //                 } catch (InterruptedException e) {//                      e.printStackTrace();//                    }//                   System.out.println(Thread.currentThread().getName() + "正在出售第"//                            + (tickets--) + "张票");//              }//           }//       }//   }

   @Override    public void run() {       while (true) {            synchronized (obj) {              if (tickets > 0) {                 try {                     Thread.sleep(100);                    } catch (InterruptedException e) {                        e.printStackTrace();                  }                 System.out.println(Thread.currentThread().getName()                           + "正在出售第" + (tickets--) + "张票");               }         }     } }}

public class SellTicketDemo { public static void main(String[] args) {      // 创建资源对象     SellTicket st = new SellTicket();

      // 创建三个线程对象       Thread t1 = new Thread(st, "窗口1");     Thread t2 = new Thread(st, "窗口2");     Thread t3 = new Thread(st, "窗口3");

       // 启动线程       t1.start();       t2.start();       t3.start();   }}

同步的好处: 可以解决多线程的安全问题
同步的弊端: 当线程相当多时,因为每个线程都会去判断同步上的锁,
这是很耗资源的,无形中降低了程序运行的效率。

A:同步代码块的锁对象是: 任意对象
B:同步方法的格式及锁对象:
把同步方法关键字加在方法上
同步方法的锁对象是this
C:静态方法及代码块是: 类的字节码对象

public class SellTicket implements Runnable {

  // 定义100张票    private static int tickets = 100;

  // 定义同一把锁 private Object obj = new Object();   private Demo d = new Demo();

   private int x = 0;

 //同步代码块用obj做锁//   @Override//  public void run() {//     while (true) {//          synchronized (obj) {//                if (tickets > 0) {//                   try {//                       Thread.sleep(100);//                  } catch (InterruptedException e) {//                      e.printStackTrace();//                    }//                   System.out.println(Thread.currentThread().getName()//                         + "正在出售第" + (tickets--) + "张票 ");//                }//           }//       }//   }

   //同步代码块用任意对象做锁//  @Override//  public void run() {//     while (true) {//          synchronized (d) {//              if (tickets > 0) {//                   try {//                       Thread.sleep(100);//                  } catch (InterruptedException e) {//                      e.printStackTrace();//                    }//                   System.out.println(Thread.currentThread().getName()//                         + "正在出售第" + (tickets--) + "张票 ");//                }//           }//       }//   }

   @Override    public void run() {       while (true) {            if(x%2==0){             synchronized (SellTicket.class) {                 if (tickets > 0) {                     try {                         Thread.sleep(100);                        } catch (InterruptedException e) {                            e.printStackTrace();                      }                     System.out.println(Thread.currentThread().getName()                               + "正在出售第" + (tickets--) + "张票 ");                  }             }         }else {//             synchronized (d) {//                  if (tickets > 0) {//                       try {//                           Thread.sleep(100);//                      } catch (InterruptedException e) {//                          e.printStackTrace();//                        }//                       System.out.println(Thread.currentThread().getName()//                             + "正在出售第" + (tickets--) + "张票 ");//                    }//               }

               sellTicket();

           }         x++;        } }

// private void sellTicket() {//     synchronized (d) {//          if (tickets > 0) {//           try {//                   Thread.sleep(100);//          } catch (InterruptedException e) {//                  e.printStackTrace();//            }//           System.out.println(Thread.currentThread().getName()//                     + "正在出售第" + (tickets--) + "张票 ");//            }//       }//   }

   //如果一个方法一进去就看到了代码被同步了,那么我就再想能不能把这个同步加在方法上呢?//   private synchronized void sellTicket() {//           if (tickets > 0) {//           try {//                   Thread.sleep(100);//          } catch (InterruptedException e) {//                  e.printStackTrace();//            }//           System.out.println(Thread.currentThread().getName()//                     + "正在出售第" + (tickets--) + "张票 ");//            }//   }

   private static synchronized void sellTicket() {       if (tickets > 0) {     try {             Thread.sleep(100);        } catch (InterruptedException e) {                e.printStackTrace();      }     System.out.println(Thread.currentThread().getName()                   + "正在出售第" + (tickets--) + "张票 ");      }}}

class Demo {}

public class SellTicketDemo { public static void main(String[] args) {      // 创建资源对象     SellTicket st = new SellTicket();

      // 创建三个线程对象       Thread t1 = new Thread(st, "窗口1");     Thread t2 = new Thread(st, "窗口2");     Thread t3 = new Thread(st, "窗口3");

       // 启动线程       t1.start();       t2.start();       t3.start();   }}

将集合变成线程安全

public class ThreadDemo {    public static void main(String[] args) {      // 线程安全的类     StringBuffer sb = new StringBuffer();        Vector<String> v = new Vector<String>();     Hashtable<String, String> h = new Hashtable<String, String>();

     // Vector是线程安全的时候才去考虑使用的,但是我还说过即使要安全,我也不用你      // 那么到底用谁呢?       // public static <T> List<T> synchronizedList(List<T> list)     List<String> list1 = new ArrayList<String>();// 线程不安全        List<String> list2 = Collections               .synchronizedList(new ArrayList<String>()); // 线程安全 }}

总结:

(1)多线程: 一个应用程序多条执行路径
进程: 正在执行的应用程序
线程: 进程的执行单元,执行路径
单线程: 一个应用程序只有一条执行路径
多线程: 一个应用程序有多条执行路径

多进程的意义: 提高CPU的使用率
多线程的意义: 提高应用程序的使用率

(2)Java程序的运行原理及JVM的启动是多线程的吗?
A:JAVA命令去启动JVM,JVM就会启动一个进程,该进程会启动主线程。
B:JVM的启动是多线程的,因为最低有两个线程启动主线程和垃圾回收线程

(3)多线程实现方案
A:继承Thread类
B:实现Runnable接口
(4)线程的调度和优先级问题
A:线程的调度 a:分时调度 b:抢占式调度(java采用该种)
B:获取和设置线程优先级 a默认是5 b范围是1-10
(5)线程的控制
A:休眠线程 B:加入线程 C:礼让线程 D:后台线程 E:终止线程
(6)线程的生命周期
A:新建 B:就绪 C:运行 D:阻塞 E:死亡
(7)多线程安全问题的原因
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
(8)同步解决线程安全问题
A:同步代码块
synchronized(对象){
需要被同步的代码
}
这里的锁对象可以是任意对象
B:同步方法
把同步加在方法上
这里的锁对象是this
C:静态同步方法
把同步加在方法上
这里的锁对象是当前类的字节码文件对象

(9)回顾以前的线程安全的类
A:StringBuffer
B:Vector
C:Hashtable
D:如何把一个线程不安全的集合类变成一个线程安全的集合类
用Collections工具类的方法即可。

传智播客风清扬视频-------线程简介相关推荐

  1. 传智播客风清扬视频-------网络编程简介

    计算机网络模型 OSI(Open System Interconnection开放系统互连)参考模型 TCP/IP参考模型 OSI 应用层--表示层--会话层--传输层--网络层--数据链路层--物理 ...

  2. 传智播客C语言视频第二季(第一季基础上增加诸多C语言案例讲解,有效下载期为10.5-10.10关闭

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 卷 ba ...

  3. 传智播客C语言视频第二季(第一季基础上增加诸多C语言案例讲解,有效下载期为10.5-10.10关闭)

    卷 backup 的文件夹 PATH 列表 卷序列号为 00000025 D4A8:14B0 J:. │  1.txt │  c语言经典案例效果图示.doc │  ├─1传智播客_尹成_C语言从菜鸟到 ...

  4. 传智播客C语言视频第二季(第一季基础上增加诸多C语言案例讲解,有效下载期为10.5-10.10关闭)...

    卷 backup 的文件夹 PATH 列表 卷序列号为 00000025 D4A8:14B0 J:. │  1.txt │  c语言经典案例效果图示.doc │  ├─1传智播客_尹成_C语言从菜鸟到 ...

  5. 传智播客C语言视频第二季 第一季基础上增加诸多C语言案例讲解,有效下载期为10 5-10 10关闭

    分享一下我老师大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow 卷 backup ...

  6. 传智播客-php基础视频,传智播客PHP核心基础视频教程推荐(资源)

    PHP,是英文超级文本预处理语言Hypertext Preprocessor的缩写.PHP 是一种 HTML 内嵌式的语言,是一种在服务器端执行的嵌入HTML文档的脚本语言,语言的风格有类似于C语言, ...

  7. java工作流 传智播客_Activiti工作流视频教学(企业开发实战讲解)_传智播客

    Activiti工作流视频教学(企业开发实战讲解)_传智播客课程简介: Activiti工作流视频教学(企业开发实战讲解)_传智播客本教学共分4天进行讲解,本站提供第1天内容在线观看,全集教学请在本站 ...

  8. 传智播客软件测试学习视频汇总:

    课程名称 分类 URL 提取码 软件测试入门到精通 视频 http://yun.itheima.com/course/490.html?aoe cnj1 资料 https://pan.baidu.co ...

  9. Java多线程(6)——Thread类中的一些方法(传智播客毕老师视频讲解)

    1.守护线程 代码如下: import java.util.concurrent.locks.*; public class StopTest implements Runnable {private ...

最新文章

  1. 工作流编程循序渐进(9:使用本地服务在宿主和工作流之间通信)
  2. ab plc软件_回收三菱PLC模块西门子模块AB模块数控模块单片机回收【三菱plc吧】...
  3. Scrapy框架的学习(3.pipeline介绍以及多个爬虫的pipeline的使用)
  4. sklearn机器学习常用过程总结
  5. 关于SAP Spartacus Routing 页面上下文切换机制的实现
  6. leetcode860. 柠檬水找零
  7. Python-装饰器进阶
  8. Unity读取TXT文本文件
  9. 天秀!花费 200W 设计的新版 “小米”图标,看看用Python怎么绘制?
  10. C语言 Linux网络编程(C/S架构) 在线词典
  11. 测试理论----软件测试四大测试过程
  12. 卡塔编程_量子卡塔教您如何在Q#中进行量子编程
  13. 小攻是鸿蒙小受是鲲鹏,洪荒之鸿蒙大天尊
  14. 论文被引上千次,GitHub 开源6000星,他们是首届字节跳动奖学金获奖者
  15. 架构设计:网络附属存储NAS,块存储EBS与对象存储OSS的比较以及选用
  16. 知道创宇发布统一云防御,“开明兽”亮相“山海·创”
  17. 保定计算机软件学院是哪个区,河北软件职业技术学院在哪个区
  18. 高清壁纸免费下载网站
  19. 细粒度图像分析综述2019
  20. 快速入门GORM,使用GORM进行CURD

热门文章

  1. 全国城市根据首字母分类json格式
  2. hive币涨幅空间大吗_HIVE币今日价格_HIVE币最新消息_HIVE币行情走势图 - 币界网
  3. CSS基础-04-浏览器调试
  4. Camera和Image sensor技术基础笔记(4) -- 白平衡White Balance
  5. 南开1809计算机应用基础在线作业,【奥鹏】南开21春学期(1709、1803、1809、1903、1909、2003、2009、2103)《计算机应用基础》在线作业1...
  6. 二、PyQtGragh模块安装以及上手体验
  7. 百数在线表单如何实现表单套打?
  8. C语言编程计算下列算式的值
  9. python中的堆栈
  10. Mysql中数据类型括号中的数字代表的含义