天天看点

认真阅读完这篇文章熟练掌握多线程相关基础知识

一、多线程概念

1、什么是程序?一个程序可以有多个进程

程序是一段静态的代码,它是应用程序执行的蓝本

2、什么是进程?一个进程可以有多个线程

进程是一种正在运行的程序,有自己的地址空间。

作为蓝本的程序可以被多次加载到系统的不同内存区域分别执行,形成不同的进程。

基于进程的特点是允许计算机同时运行两个或更多的程序。

3、什么是线程?

线程是进程内部单一的一个顺序控制流。一个进程在执行过程中,可以产生多个线程,每个线程也有自己产生,存在和消亡的过程。

4、什么是并发?

并发当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只 能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行 时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。

5、什么是并行?

当系统有一个以上CPU时,则线程的操作有可能非并发。当一个CPU执行一个线程时,另一个CPU可 以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行 (Parallel)。

6、并发与并行的区别

并发和并行是即相似又有区别的两个概念,并行是指两个或者多个事件在同一时刻发生;而并发是 指两个或多个事件在同一时间间隔内发生。在多道程序环境下,并发性是指在一段时间内宏观上有多个程 序在同时运行,但在单处理机系统中,每一时刻却仅能有一道程序执行,故微观上这些程序只能是分时地 交替执行。倘若在计算机系统中有多个处理机,则这些可以并发执行的程序便可被分配到多个处理机上, 实现并行执行,即利用每个处理机来处理一个可并发执行的程序,这样,多个程序便可以同时执行。

二、实现多线程类方法

1、Runnable接口

public class Th1 implements Runnable {
    public void run() {
        System.out.println("th1");
    }
}      

2、继承Thread类

public class Th2 extends Thread {
    public void run() {
        System.out.println("th2");
    }
}      

3、Callable 接口

public class Th3 implements Callable<Integer> {
    public Integer call() {
        System.out.println("call");
        return 300;
    }

}      

test类:

package duoxiancheng;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author yeqv
 * @program A2
 * @Classname test
 * @Date 2022/1/27 22:33
 * @Email [email protected]
 */
public class test {
    public static void main(String[] args) {
        //实例化Th3
        Th3 th3 = new Th3();
        // 执行 Callable 方式,需要 FutureTask 实现类的支持
        // FutureTask 实现类用于接收运算结果, FutureTask 是 Future 接口的实现类
        FutureTask<Integer> result = new FutureTask<>(th3);
        //开启线程
        new Thread(result).start();
        try {
            //当线程执行完成后返回结果打印出来
            System.out.println(result.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
}      

4、综合线程实现

package duoxiancheng;

/**
 * @author yeqv
 * @program A2
 * @Classname Test1
 * @Date 2022/1/27 22:59
 * @Email [email protected]
 */
public class Test1 {
    public static void main(String[] args) {
        //建立方法一 实现Runnable接口,并作为Thread类参数
        //lambda表达式创建多线程并开启
        new Thread(() -> {
            System.out.println("t1");
        }).start();
        //创建新的多线程对象,参数是之前定义过的一个多线程类对象
        Thread t2 = new Thread(new Th1());
        //启动新多线程对象
        t2.start();
        //建立方法二 继承Thread 类,重写run方法
        var t3 = new Th2();
        //改线程名字
        t3.setName("线程三");
        //打印线程名
        System.out.println(t3.getName());
        //开启线程
        t3.start();

    }
}      
package duoxiancheng;

import java.util.concurrent.TimeUnit;

/**
 * @author yeqv
 * @program A2
 * @Classname Test2
 * @Date 2022/1/27 23:20
 * @Email [email protected]
 */
public class Test2 {
    public static void main(String[] args) {
        //多线程 方法一 继承Thread
        var t1 = new Thread() {
            @Override
            public void run() {
                this.setName("one thread");
                System.out.println(this.getName());
            }
        };
        t1.setName("one1111 thread");
        System.out.println(t1.getName());
        t1.start();
        //多线程 方法二 实现接口,实现Thread作为参数
        var t2 = new Runnable() {
            public void run() {
                String n = Thread.currentThread().getName();
                System.out.println(n);
            }
        };
        var t22 = new Thread(t2, "two thread");
        t22.setName("two2222 thread");
        t22.start();
        //main线程输出
        try {
            TimeUnit.SECONDS.sleep(2);
            Thread.currentThread().setName("main thread");
            System.out.println(Thread.currentThread().getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}      

三、多线程状态及常用方法

认真阅读完这篇文章熟练掌握多线程相关基础知识

JAVA线程具有的五种基本状态:

1、新建状态(New):

当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

2、就绪状态(Runnable):

当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

3、运行状态(Running):

当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就 绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

4、阻塞状态(Blocked):

处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

1,等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

2,同步阻塞 : 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

3,其他阻塞 : 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):

线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

package duoxiancheng;

/**
 * @author yeqv
 * @program A2
 * @Classname Test3
 * @Date 2022/1/27 23:40
 * @Email [email protected]
 */
public class Test3 {
    public static void main(String[] args) {
        //新建线程
        var t = new Thread(() -> {
            System.out.println("ttttt");
        });
        //更改线程优先级
        t.setPriority(Thread.MAX_PRIORITY);
        //启动线程
        t.start();
    }
}