java多线程实现方式的应知应会

进程与线程

进程:是指一个内存中运行的应用程序。

比如鼠标点击应用程序“记事本”,“记事本”程序进入到内存中,占用了一些内存执行的这个程序就是进程。

线程:线程则是进程的一个执行路径;一个进程中至少有一个线程,进程中的多个线程共享进程的资源。
在这里插入图片描述

比如运行360安全卫士,该程序就会进入到内存中,即启动了进程;当我们运行安全卫士的某个功能,比如木马查杀,则该进程就会开启一个执行路径,进行电脑上的木马查杀工作;同时当我们运行电脑清理这个功能时,进程又会开启另一个执行路径,进行电脑清理工作,运行系统修复、优化加速功能同样如此,这些开启的执行路径,即是线程,也就是说一个进程中会存在多个线程,多个线程可以并发处理。

线程调程

1、分时调度

是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片。

2、抢占式调度

是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。

Java虚拟机采用的是抢占式调度。

主线程的定义

当Java程序启动时,一个线程立刻运行,则该线程通常叫做程序的主线程(main thread)。

/**
 * @author zhuhuix
 */
public class MainThread {

    //程序启动时main方法立刻执行,即启动主线程
    public static void main(String[] args) {
        //主线程启动后通过循环依次打印1-100
        for (int i=1;i<=100;i++){
            System.out.println("主线程打印:"+i);
        }

        //主线程完成以上打印后再循环依次打印A-Z
        for (char c='A';c<='Z';c++){
            System.out.println("主线程打印:"+c);
        }

    }
}

主线程运行输出的打印结果如下:
在这里插入图片描述

创建多线程的第一种方式:创建Thread类的子类

  1. 创建一个Thread类的子类
  2. 在Thread类的子类中重写run方法:设置线程任务
  3. 创建Thread类的子类对象
  4. 调用Thread类中的成员方法start方法,开启新的线程:即执行run方法
/**
 * 通过继承Thread类创建多线程程序
 * 
 * @author zhuhuix
 */
public class Thread01 extends Thread {
    //通过重写run方法设置线程任务
    @Override
    public void run() {
        for (char c='A';c<='Z';c++){
            System.out.println("子线程打印:"+c);
        }
    }
}

/**
 * 多线程打印输出
 * @author zhuhuix
 */
public class MainThread {

    public static void main(String[] args) {

        //创建继承于Thread类的子类对象
        Thread01 thread01 = new Thread01();
        //调用Thread类的成员方法start启线线程任务
        thread01.start();

        //主线程启动后通过循环依次打印1-100
        for (int i = 1; i <= 100; i++) {
            System.out.println("主线程打印:" + i);
        }

    }
}

执行结果如下图:(主线程与子线程通过抢占CPU资源完成各自地打印输出任务,抢占CPU资源具有随机性)
在这里插入图片描述

多线程的内存图

多线程执行时,其实每一个执行线程都有一片自己所属的栈内存空间。进行方法的压栈和弹栈,这样也就给CPU开了多个执行路径,可以进行并发执行。
在这里插入图片描述

Thread的常用方法

获取线程名称与设置线程名称 :

/**
 * 通过继承Thread类创建多线程程序
 *
 * @author zhuhuix
 */
public class Thread01 extends Thread {
    //通过重写run方法设置线程任务
    @Override
    public void run() {

        //获取当前子线程名称
        String currentThreadName=Thread.currentThread().getName();

        for (char c='A';c<='Z';c++){
            System.out.println(currentThreadName+":"+c);
        }
    }
}

/**
 * @author zhuhuix
 */
public class MainThread {

    public static void main(String[] args) {

        //创建继承于Thread类的子类对象
        Thread01 thread01 = new Thread01();
        //调用Thread类的成员方法start启线线程任务
        thread01.start();

        //创建继承于Thread类的子类对象
        Thread01 thread02 = new Thread01();
        //通过setName设置线程名称
        thread02.setName("子线程2");
        //调用Thread类的成员方法start启线线程任务
        thread02.start();

        //主线程启动后通过循环依次打印1-100
        for (int i = 1; i <= 100; i++) {
            System.out.println("主线程打印:" + i);
        }

    }
}

执行效果如下:
在这里插入图片描述
Sleep方法:
对正在执行的线程以指定的毫秒数暂停执行

/**
 * 通过继承Thread类创建多线程程序
 *
 * @author zhuhuix
 */
public class Thread01 extends Thread {
    //通过重写run方法设置线程任务
    @Override
    public void run() {

        //打印当前子线程名称
        String currentThreadName=Thread.currentThread().getName();

        for (char c='A';c<='Z';c++){
            System.out.println(currentThreadName+":"+c);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

/**
 * 使用sleep方法
 * @author zhuhuix
 */
public class ThreadSleep {
    //程序启动时main方法立刻执行,即启动主线程
    public static void main(String[] args) throws InterruptedException {

        //创建继承于Thread类的子类对象
        Thread01 thread01 = new Thread01();
        //调用Thread类的成员方法start启线线程任务
        thread01.start();


        //主线程启动后通过循环依次打印1-100
        for (int i = 1; i <= 100; i++) {
            System.out.println("主线程打印:" + i);
            Thread.sleep(1000);
        }

    }
}

执行效果如下:
在这里插入图片描述

创建多线程的第二种方式:声明实现Runnable接口的类

  1. 创建一个实现Runnable接口的实现类
  2. 在该实现类中重写run方法:设置线程任务
  3. 创建一个实现类的对象
  4. 创建Thread类对象,构造方法中传递这个实现类
  5. 调用Thread类对象的start方法,开启新的线程。
/**
 * 通过创建实现Runnable接口的类实现多线程程序
 *
 * @author zhuhuix
 */
public class Thread02 implements Runnable {
    @Override
    public void run() {
        for (char c = 'A'; c <= 'Z'; c++) {
            System.out.println("子线程打印:" + ":" + c);

        }
    }
}

public class ThreadMethod {

    public static void main(String[] args) {

        //创建实现了Runnable接口的实现类的对象
        Thread02 thread02 = new Thread02();
        //创建一个Thread类的对象,构造函数中传递实现了Runnable接口的实现类的对象
        //调用Thread类的对象的方法start,启动多线程任务
        new Thread(thread02).start();

        //主线程启动后通过循环依次打印1-100
        for (int i = 1; i <= 100; i++) {
            System.out.println("主线程打印:" + i);
        }
    }
}

执行效果如下:
在这里插入图片描述

实现Runnable接口创建多线程程序的好处:

  • 由于java的类只能继承一个类,即如果一个类继承了Thread类就不能继承其他的类;而实现Runnable的接口的实现类,还可以继承其他类。
  • 实现Runnable接口创建多线程,可以利用接口式方式编程的优点,把设置线程任务和开启新线程进行分离与解藕。

结论:一般我们创建多线程程序,尽量采用实现Runnable接口的创建方式。

原创文章 56 获赞 8 访问量 4723

猜你喜欢

转载自blog.csdn.net/jpgzhu/article/details/105902497
今日推荐