java中线程实现的两种方式(Thread 和 Runnable)

时间:2022-03-03 14:38:06

首先,我们需要了解一些基本知识:

微观概念:
并行: 指两个或多个事件在同一时刻点发生
并发: 指两个或多个事件在同一时间段内发生


一、进程(Process)与线程(thread)


    进程:运行的应用程序和所占用的资源,是指一个内存中运行的应用程序。
      每个进程都有自己独立的一个内存空间(数据交互困难),
      一个应用程序可以同时启动多个进程。比如同时听音乐和看小说
  
    线程:进程中单个任务执行流,是指进程中的一个执行任务(控制单元),一个进程可以同时并发运行多个线程
       多任务系统,该系统可以运行多个进程,一个进程可以 执行多个任务,一个进程包含多个线程
   
 多线程:一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个执行任务,即多线程


 简单点:在操作系统中允许多个任务,每一个任务就是一个进程,每一个进程也可以执行多个任务,
        每个任务就是一个线程,任务之间依靠线程进行通信

    注意:因为一个进程中的多线程是并发进行的,那么从微观角度上来考虑也是有先后顺序的,那么哪个线程
      先执行完全取决于CPU调度器(java线程一般取决于JVM),程序员控制不了


二、多线程的优势


     1.进程之间不能共享内存,而线程之间共享内存(堆内存)
     2.系统创建进程时需要为该进程重新分配系统资源,创建线程则代价小很多,因此实现多任务并发时,多线程效率更高
     3.Java语言本身内置多线程功能的支持,而不是单纯作为底层系统的调度方式,从而简化了多线程编程
     4.多线程下载(网络带宽) 即一个线程就是一个文件的下载通道,多线程就是同时开启了多个下载通道
        bit位  byte字节  1024kb/s  -> 1024/8 128

比如 单行道与多行道 LOL CS


三、创建和启动线程  【重点】


 方式一:继承Thread类
 
 步骤:1.定义一个类继承Thread类
     2.在该类中覆盖Thread类中的run方法
     3.在run方法中实现需要执行的操作(注明线程执行体)
4.在main方法(线程)中,创建线程对象,并调用start()方法启动线程
A类 a = new A类();
a.start();

     eg:

package com.javaweb.practice;

public class MyThread extends Thread{

        public MyThread(String name){
            super(name);
        }

        public void run(){
            for(int i=0 ; i<10 ; i++){
                System.out.println(getName()+":正在执行!"+i);
            }
        }

}

package com.javaweb.practice;

import java.util.Date;

public class Test extends Date {

    public static void main(String[] args) {
        MyThread mt = new MyThread("新的线程");
        mt.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程!"+i);
        }

    }

}

结果:

        main线程!0
        main线程!1
        main线程!2
        main线程!3
        main线程!4
        main线程!5
        main线程!6
        main线程!7
        新的线程:正在执行!0
        新的线程:正在执行!1
        新的线程:正在执行!2
        新的线程:正在执行!3
        新的线程:正在执行!4
        新的线程:正在执行!5
        新的线程:正在执行!6
        新的线程:正在执行!7
        新的线程:正在执行!8
        新的线程:正在执行!9
        main线程!8
        main线程!9


java中线程实现的两种方式(Thread 和 Runnable)

注意:千万不要使用对象调用run方法,如果调用run方法,等于就是只启动了一个线程,未开启别的线程

方法:getName(): 拿到当前线程的名称
            setName(String name): 给当前线程的名字赋值
            currentThread() 返回对当前正在执行的线程对象的引用。
    sleep() 当前线程睡眠,让其他线程抢CPU资源




方式二:实现Runnable接口
 
步骤:1.定义一个类A实现Runable接口,注意A类不是线程类
  2.在A类中覆盖Runable接口中的run方法
  3.在run方法中实现需要执行的操作(注明线程执行体)
  4.在main方法(线程)中,创建线程对象,并调用start()方法启动线程
     Thread t = new Thread(new A());

      t.start();

   eg:

package com.javaweb.practice;

import java.util.Currency;

public class MyRunnable implements Runnable {
    public void run() {
        for(int i=0 ; i<10 ; i++){
            System.out.println("线程"+i);
        }
    }
}

package com.javaweb.practice;

public class Test  {

    public static void main(String[] args) {
        //创建线程执行目标类对象
        MyRunnable runn = new MyRunnable();
        //将Runnable接口的子类对象作为参数传递给Thread类的构造函数
        Thread thread01 = new Thread(runn,"线程1");
        Thread thread02 = new Thread(runn,"线程2");
        //开启线程
        thread01.start();
        thread02.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程!"+i);
        }

    }

}

 四 继承方式与实现方式的区别:

  继承方式:
           1.java中类是单继承的,如果继承了Thread,该类就不能再有其他直接父类了
   2.从操作上来分析,继承方式更简单,获取线程的名称也简单
   3.从多线程共享同一个资源上分析,继承方式不能做到
   
  实现方式推荐使用:
           1.java中的类可以实现多个接口,此类还可以继承其他的类
   2.操作上实现方式稍微复杂点,获取名称只能通过Thread.currentThread().getName()来拿
               3.从多线程共享一个资源上,实现方式才能做到是否共享同一个资源


         推荐使用 实现方式


五、线程的生命周期

         1. 新建 :  new thread实例对象

         2. 就绪 :  调用start() 启动线程进入就绪

         3. 运行 :运行run方法里面的代码 

         4. 中断(阻塞):正在运行的线程由于外部原因引起当前线程中断或阻塞,等到引起阻塞原因消失,回到就绪状态

         5.死亡  : 中断线程