Java多线程-基础篇(一)

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:57   2548   0

多线程---基础篇,本文主要针对多线程的基础进行复习,内容包括线程的理解,创建方式,Thread类函数理解;
1、线程的理解:OS系统角度:每个运行的程序都会被操作系统创建对应的进程(包括分配的资源、PCB等),进程是操作系统分配资源的基本单位(理解:程序运行需要空间,操作系统创建对应进程时就为之分配了相应的空间),切换进程时需要作中断处理、保护现场等,使得系统的并发度受到一定影响;为了提高并发度,提出了线程的概念,线程可理解为一个更小的进程,一个进程可以创建多个线程,它们共享进程的资源,同时拥有自己的一些资源(如堆栈空间,很小),那么OS在线程中切换就不像切换进程那么耗费资源了,从而并发度就提高了。
总之:线程时进程的一部分,在执行JAVA程序时,OS为之创建一个进程,该进程又可创建多个线程,即所谓的单进程多线程。
2、线程的两种创建方式
线程是要执行代码的,即要完成任务的,所以创建线程之前必须明白线程要做什么,即任务是什么?=>任务当然就是run()方法里面的内容了
(1)继承Thread类,覆盖其run()方法,如下代码:以内部类的方式创建线程

  //线程的第一种创建方式,继承Thread类,覆盖run()方法
  new Thread(){
   private int i=0;
   public void run(){
    for(int i=0;i<100;i++){
     System.out.println("Thread....i="+i);
    }
   }
  }.start();
注意:start()方法为Thread类中的方法,该方法有两个作用,一是开启线程,二是调用run()方法
(2)实现Runnable接口

  //线程的第二种创建方式,实现Runnable接口,覆盖run()方法
  new Thread(new Runnable(){
   public void run(){
    for(int i=0;i<100;i++){
     System.out.println("Runnable....i="+i);
    }
   }
  }).start();

两种方式对比:如果查看许多优秀的多线程代码,你可以发现,大多数采用了后者方式创建进程,WHY?我们应该从OOP的角度思考问题,任务是什么?任务中有自己的执行方式,有自己的属性,所以我们应该将任务封装成为一个类,第二种方式将线程与任务分开,将OOP的思想运用到了。
考题:以下方式创建线程会执行哪个run()方法?

  new Thread(new Runnable(){
   public void run(){
    for(int i=0;i<10;i++)
     System.out.println("2....");
   }
  }){
   public void run(){
    for(int i=0;i<10;i++)
     System.out.println("1....");
   }
  }.start();
答案:输出1....,即执行下面哪个run()方法。
解析:此题设计内部类的一些知识,这样创建线程意思:创建了一个内部类,即Thread的子类,并实现了run()方法(打印1....),在创建该对象时,调用的不是默认的构造函数,而是调用的带参数的构造函数,传递了一个Runnable实例对象,也实现了run()方法(打印2...);此时该调用哪个?实际上回到面向对象的思想上,参阅JDK文档,Thread类时实现了Runnable接口的,故Thread类实现了run()方法,它内部实际存在一个Runnable实例task,若Thread类的实例调用run()方法,实际上进行了判断

 if(task!=null){
  task.run();//其中task时Runnable的一个实例
 }
task就是我们封装的任务类的实例,所以通过Runnable创建线程的原理大家应该明白了,那现在Thread的子类又实现了run()方法,子类的方法会覆盖父类的run()方法,所以start()开启的是子类的run()方法。

3、Thread类的方法
Thread类包含了许多控制线程的方法,如静态方法Thread.currentThread()得到当前正在执行的线程,成员方法:start()、isAlive()、setPriority(p:int)、join()、sleep(mills:long)、yield()等。
其中setProority(p:int)设置优先级,并不代表优先级高的线程一定会先执行,应该理解为线程获得CPU的概率更高;join()方法:使得当前线程放弃CPU,调用者获得CPU执行,调用者执行完后才恢复之前的线程执行;sleep()为暂停当前的执行线程。
  Thread t1=new Thread(new Runnable(){
   public void run(){
    for(int i=0;i<100;i++)
     System.out.println(Thread.currentThread().getName()+"...2....");
   }
  });
  Thread t2=new Thread(){
   public void run(){
    for(int i=0;i<100;i++){
     System.out.println(Thread.currentThread().getName()+"...1....");
    }
   }
  };
  Thread t3=new Thread(){
   public void run(){
    for(int i=0;i<100;i++)
     System.out.println(Thread.currentThread().getName()+"...3....");
   }
  };
  t1.setPriority(Thread.MAX_PRIORITY);
  t2.setPriority(Thread.NORM_PRIORITY);
  t3.setPriority(Thread.MIN_PRIORITY);
  t1.start();
  t2.start();
  t3.start();
输出结果为:

Thread-1...1....
Thread-2...3....
Thread-0...2....
Thread-2...3....
Thread-1...1....
Thread-2...3....
可以看到,优先级高的线程不总是能抢到CPU资源。


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP