根据案例引出线程的创建和启动: 并发的干一件事情(企图并发) 读数据库的过程中往磁盘里写入数据(模拟)

  • 为了显得慢一点让它休眠(Thread.sleep)一下,sleep后面会详细说,这里可以暂时理解为线程进入 block 状态。

  • 想要的效果是让这两个方法同时去执行。

  • 大家可以看到它并没有交替的去执行而是等readFromDataBase()方法执行完后writeDataToFile()方法才执行,这就导致了程序只能一件事情一件事情的去处理,不能同时处理。

  • 再比如有两块要执行的代码逻辑单元,它同样也是一步一步的顺序去执行,并不会是交替(同时)的去执行。

      public static void main(String[] args) {
    
          for(int i = 0; i<=1000; i++) {
              System.out.println("Task 1=>" + i);
          }
    
          for(int j = 0; j<=1000; j++) {
              System.out.println("Task 2=>" + j);
          }
      }
    
  • 运行效果

  • 只有等i全部输出完后才会去执行j的东西那么怎样才能同时去运行呢? 我们先来看些Java对多线程的支持

  • 根据Java官方文档可以看出刚才写的程序,其实有意无意的已经创建了一个线程,这个线程是main线程。

  • 如何去验证“当虚拟机启动的时,通常有一个非守护线程呢”?

  • 先让这个程序休眠的时间长一点打开JConsole工具看一看

  • JVM创建一个main线程,也就是说整个Application有一个main函数,它就是根据main函数创建一个main线程,然后这个mian函数被调用,调用的时候会开辟一个线程,这个线程的名字就叫main,也就是说JVM启动的时候创建了一个守护线程和非守护线程。

  • 那么怎么创建一个线程让readFromDataBase()方法执行完后writeDataToFile()方法是并发\并行去执行的?

  • 根据官方文档说,有两种方式创建一个线程,第一种方式是声明一个clss他是Thread的子类,这种方式需要覆盖run方法,这个实例一但启动然后他就是一个线程。

  • 这里我写了一个内部类 然后重写run方法,然后把要执行的代码逻辑单元放进去:

      public static void main(String[] args) {
          // READ-Thread 是给线程起的名字 
          Thread t = new Thread("READ-Thread"){
              @Override
              public void run() {
                  for(int i = 0; i<=1000; i++) {
                      System.out.println("Task 1=>" + i);
                  }
              }
          };
      }
    
  • 这时候Thread只是Java的一个实例而已,他和任何Java的实例都一模一样,并不代表他是个线程,只有把他启动之后才会是一个线程,而且这个启动是立即返回的,他不是一个block 方法。

      public static void main(String[] args) {
          // 内部类
          Thread t = new Thread(){
              @Override
              public void run() {
                  for(int i = 0; i<=1000; i++) {
                      System.out.println("Task 1=>" + i);
                  }
              }
          };
    
          t.start()
    
          for(int j = 0; j<=1000; j++) {
              System.out.println("Task 2=>" + j);
          }
      }
    
  • 现在就有两个线程了一个是t,一个是main函数执行的。

  • 运行效果

  • 现在我们回过头来看看前面提到的,读数据库的过程中将数据写入文件:

      public static void main(String[] args) {
          // 匿名内部类
          // READ-Thread 为线程名称
          new Thread("READ-Thread"){
              @Override
              public void run() {
                  readFromDataBase();
              }
          }.start();
    
          new Thread("WRITE-Thread"){
              @Override
              public void run() {
                  writeDataToFile();
              }
          }.start();;。 
      }
    
  • 运行效果

  • 这时候就有交替(由CPU去切换执行权)的情况了,但是线程有比较头疼的地方,这个执行顺序会引发一些安全的一些问题。

  • 创建线程的方式这里根据内部类和匿名内部类的方式去做的,大家也可以去写一个Thread的子类,然后重写里面的run方法然后再去调用:

      public class MyThread extends Thread { 
          @Override 
          public void run() { 
              for(int i = 0; i<=1000; i++) {
                  System.out.println("Task 1=>" + i);
              }
          } 
      } 
    
      public static void main(String[] args) { 
          MyThread thread = new MyThread(); 
          thread.start(); 
      }
    
  • 第二种实现接口的方法以后再说

results matching ""

    No results matching ""