Java SE多线程部分--18.多线程

版权声明:转载请注明原始链接 https://blog.csdn.net/sswqzx/article/details/82876874

1、概述

多线程:指的是这个程序(一个进程)运行时产生了不止一个线程

2、并发与并行

并行:指两个或多个事件在同一时刻(时间点)发生(同时发生)。
并发:指两个或多个事件在同一个时间段内发生。

3、线程与进程

进程:是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以同时运行多个进程;进程也是程序的一次执行过程,是系统运行程序的基本单位;系统运行一个程序即是一个进程从创建、运行到消亡的过程。


线程:进程内部的一个独立执行单元;一个进程可以同时并发的运行多个线程,可以理解为一个进程便相当于一个单 CPU 操作系统,而线程便是这个系统中运行的多个任务。

4、创建多线程第一种方法:继承

Java使用java.lang.Thread 类代表线程

Thread构造方法:

public Thread() :分配一个新的线程对象。
public Thread(String name) :分配一个指定名字的新的线程对象。
public Thread(Runnable target) :分配一个带有指定目标新的线程对象。
public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字。

Thread常用方法:

public String getName() :获取当前线程名称。
public void start() :导致此线程开始执行; Java虚拟机调用此线程的run方法。
public void run() :此线程要执行的任务在此处定义代码。
public static void sleep(long millis) :使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

创建线程步骤:

1. 定义Thread类的子类,并重写该类的run()方法,该run()方法的方法体就代表了线程需要完成的任务,
因此把run()方法称为线程执行体。
2. 创建Thread子类的实例,即创建了线程对象
3. 调用线程对象的start()方法来启动该线程

演示:

// 步骤一 : 自定义类, 继承 Thread 类. 我们就可以称呼该类为 `线程类`.
public class MyThread extends Thread {

    // 步骤二 : 自定义类重写 Thread 类的 run() 方法.该方法是子线程执行的入口.
    @Override
    public void run() {

        // 循环
        for (int i = 0; i < 10; i++) {
            System.out.println(getName() + " -> run ... " + i);
        }
    }
}
public class Test1 {
    public static void main(String[] args) {

        // 步骤三 : 创建一个自定义线程类的对象.
        MyThread myThread = new MyThread();

        // 更改子线程名称 :
        myThread.setName("下载线程");

        // 步骤四 : 启动子线程. 调用 start 方法.
        myThread.start();

        // 主线程
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
        }
    }
}

5、创建多线程第二种方法:接口

java.lang.Runnable 也是非常常见的一种,我们只需要重写run方法即可。

创建线程步骤:

采用java.lang.Runnable
1. 定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
3. 调用线程对象的start()方法来启动线程。

演示:

// 步骤一 : 自定义类, 实现 Runnable 接口.  说明: run 方法是封装线程执行任务的方法.
public class MyRunnable implements Runnable {

    // 步骤二 : 自定类重写 Runnable 接口定义的 run 抽象方法.
    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
        }
    }
}

测试类:

public class MyRunnableTest {
    public static void main(String[] args) {

        // 步骤三 : 创建一个自定义类的对象. (这个自定义对象也可以被称为 `任务类` 对象)
        MyRunnable myRunnable = new MyRunnable();

        // 步骤四 : 创建一个 Thread 类对象, 然后将 `任务类` 对象作为参数传递给 Thread 类的构造方法.
        Thread thread = new Thread(myRunnable, "上传线程");

        // 步骤五 : 使用 Thread 类对象调用 start 方法启动子线程.
        thread.start();

        // 主线程执行代码 ...
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " -> run ... " + i);
        }
    }
}

6、匿名内部类实现多线程

匿名 :

1. 匿名子类.     new Thread(){}.start(); 创建了一个 Thread 类的匿名子类对象.并启动了子线程.
2. 匿名实现类.   new Thread(new Runnable(){重写run方法}); Runnable的匿名实现类.

演示代码:

package com.blog.test;

public class TestThread {
    public static void main(String[] args) {

        // 匿名子类 :
        new Thread(){
            @Override
            public void run() {
                /*for (int i = 0; i < 100; i++) {
                    System.out.println("匿名子类 -> run ... " + i);
                }*/
                while (true) {
                    System.out.println("匿名子类 -> run ... ");
                }
            }
        }.start();

        // 匿名实现类 :
        new Thread(new Runnable() {
            @Override
            public void run() {
                /*for (int i = 0; i < 100; i++) {
                    System.out.println("实现类 -> run ... " + i);
                }*/
                while (true) {
                    System.out.println("匿名实现类 -> run ... ");
                }
            }
        }).start();

        // 主线程执行代码 ...
        while (true) {
            System.out.println(Thread.currentThread().getName() + " ---------------> run ... ");
        }

    }
}

7、Thread和Runnable的区别

如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。

总结:
实现Runnable接口比继承Thread类所具有的优势:
A. 适合多个相同的程序代码的线程去共享同一个资源。
B. 可以避免java中的单继承的局限性。
C. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
D. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。

E.继承方案实现多线程, 在多线程中操作共享资源需要将共享资源定义为 `静态属性资源`.
扩充:在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用
java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM其实在就是在操作系统中启动了一个进

猜你喜欢

转载自blog.csdn.net/sswqzx/article/details/82876874