九、多线程

9.1 并发与并行

  • 并发:指两个或多个事件在同一个时间段内发生;
  • 并行:指两个或多个事件在同一时刻发生(同时发生)。
    在这里插入图片描述

注意:单核处理器的计算机肯定是不能并行的处理多个任务的,只能是多个任务在单个CPU上并发运行。同理,线程也是一样的,从宏观角度上理解线程是并行运行的,但是从微观角度上分析却是串行运行的,即一个 线程一个线程的去运行,当系统只有一个CPU时,线程会以某种顺序执行多个线程,我们把这种情况称之为线程调度

9.2 线程与进程

  • 进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。
  • 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。

简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程。
所有线程都可以共享进程的资源。

9.3 创建线程类

Java使用 java.lang.Thread 类代表线程,所有的线程对象都必须是Thread类或其子类的实例。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。Java使用线程执行体来代表这段程序流。

  • Java中通过继承Thread类来创建并启动多线程的步骤如下:

    1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,因此把 run()方法称为线程执行体;
    2. 创建Thread子类的实例,即创建了线程对象 ;
    3. 调用线程对象的start()方法来启动该线程。
    /**
    *教师类
    **/
    public class Teacher extends Thread {
       private String tname;
       private int age;
       @Override
       public void run() {
           while(true)
           {
               System.out.println("教师:大家好我是" + tname);
           }
       }
       public String getTname() {
           return tname;
       }
       public void setTname(String tname) {
           this.tname = tname;
       }
       public int getAge() {
           return age;
       }
       public void setAge(int age) {
           this.age = age;
       }
       public Teacher(String name, int age) {
           this.tname = name;
           this.age = age;
       }
       public Teacher() {
       }
    }
    
    /**
    *学生类
    **/
    public class Student extends Thread {
        /**
         * 多线程执行代码方法
         */
        @Override
        public void run()
        {
           while(true)
           {
               System.out.println("学生:大家好我是" + stuname);
           }
        }
        private String stuname;
        private int age;
        public String getStuname() {
            return stuname;
        }
        public void setStuname(String stuname) {
            this.stuname = stuname;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student() {
        }
        public Student(String name, int age) {
            this.stuname = name;
            this.age = age;
        }
    }
    
    /**
    *测试类
    **/
    public class Test {
        public static void main(String[] args) {
            Student stu1=new Student("张三",21);
            Teacher t=new Teacher("赵老师",32);
           // stu1.run();
            //启动一次线程
            stu1.start();
            //t.run();
            //启动一次线程
            t.start();
        }
    }
    
  • 实现Runnable接口
    创建一个类实现Runnable接口,然后重写run方法
    创建实现类对象、代理类对象,然后代理类对象调用start()方法启动线程

    /**
    *教师类
    **/
    public class Teacher implements Runnable {
        private String tname;
        private int age;
        @Override
        public void run() {
            while(true)
            {
                System.out.println("教师:大家好我是" + tname);
            }
        }
        public String getTname() {
            return tname;
        }
        public void setTname(String tname) {
            this.tname = tname;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Teacher(String name, int age) {
            this.tname = name;
            this.age = age;
        }
        public Teacher() {
        }
    }
    
    /**
    *学生类
    **/
    public class Student implements Runnable {
        /**
         * 多线程执行代码方法(重写run方法)
         */
        @Override
        public void run() {
            while (true) {
                System.out.println("学生:大家好我是" + stuname);
            }
        }
        private String stuname;
        private int age;
        public String getStuname() {
            return stuname;
        }
        public void setStuname(String stuname) {
            this.stuname = stuname;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student() {
        }
        public Student(String name, int age) {
            this.stuname = name;
            this.age = age;
        }
    }
    
    /**
    *测试类
    **/
    public class Test {
        public static void main(String[] args) {
            Student stu1 = new Student("张三", 21);
            Teacher tea1 = new Teacher("赵老师", 32);
    
            Thread t1 = new Thread(stu1);
            Thread t2 = new Thread(tea1);
    
            t1.start();
            t2.start();
        }
    }
    
  • 实现java.util.concurrent并发包下的Callable接口(一般不用)

    创建一个类实现Callable接口,然后重写call方法并声明异常

    创建一个实现类对象,执行Callable方式,需要FutureTask实现类的支持,用于接收计算结果,并创建一个线程代理类对象,启动线程。

/**
   * 学生类
   */
public class Student3 implements Callable {
    @Override
    public Integer call() throws Exception {
        for(int i=0;i<=10;i++){
            System.out.println(sname + "是一名学生!");
        }
        return null;
    }
    private String sname;
    private int age;
    public String getSname() {
        return sname;
    }
    public void setSname(String sname) {
        this.sname = sname;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student3(String sname, int age) {
        this.sname = sname;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sname='" + sname + '\'' +
                ", age=" + age +
                '}';
    }
}

/**
  * 教师类
  */
public class Teacher3 implements Callable {
    @Override
    public Integer call() throws Exception {
        for(int i=0;i<=10;i++){
            System.out.println(tname + "是一名老师!");
        }
        return null;
    }
    private String tname;
    private int age;
    public String getTname() {
        return tname;
    }
    public void setTname(String tname) {
        this.tname = tname;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Teacher3(String tname, int age) {
        this.tname = tname;
        this.age = age;
    }
    @Override
    public String toString() {
        return "Teacher{" +
                "tname='" + tname + '\'' +
                ", age=" + age +
                '}';
    }
}

 /**
   * 测试类
   */
public class ThreadDemo1 {
    public static void main(String[] args) {
        /**
         * 实现Callable接口,实现多线程
         */
        Student3 stu3 = new Student3("李四",21);
        Teacher3 tea3 = new Teacher3("老葛",30);

        //需要FutureTask实现类的支持,用于接收计算结果
        FutureTask stuFt = new FutureTask(stu3);
        FutureTask teaFt = new FutureTask(tea3);

        //创建线程代理类
        Thread t1 = new Thread(stuFt);
        Thread t2 = new Thread(teaFt);

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