线程学习笔记

一.线程的基本介绍

什么是线程

线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实 际运作单位.

线程的执行逻辑

mark

为什么会有线程

在多核CPU中,利用多线程可以实现真正意义上的并行执行
在一个应用进程中,会存在多个同时执行的任务,如果其中一个任务被阻塞,将会起 不依赖该任务的任务也被阻塞.通过对不同任务创建不同的线程去处理,可以提高程 序处理的实时性
线程可以认为是轻量级的线程,所以线程的创建、销毁比进程快.

二.线程的应用场景

为什么要用多线程

异步执行
利用多CPU资源实现真正意义上的并行执行

线程的价值

mark

应用场景

使用多线程实现文件下载
后台任务: 如定向大量(100W以上)的用户发送邮件
异步处理: 记录日志
多步骤的任务处理,可根据步骤特征选用不同个数和特征的线程来协作处理,多任务 的分割,由一个主线程分割给多个线程完成
总结:
多线程的本质是:合理的利用多核心CPU资源来实现线程的并行处理,实现同一个线程内的多个任务的并行执行,同时基于线程本身的异步执行特性,提高任务处理的效率

三.如何在JAVA中引用多线程

使用多线程的方式

继承Thread类
/**
 * Created by 于占峰 on 2020/3/28/028.
 * 继承Thread类 重写run方法
 */
public class ThreadDemoBean extends Thread {
    @Override
    public void run() {
        System.out.println("当前线程:"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        ThreadDemoBean threadDemoBean = new ThreadDemoBean();
        threadDemoBean.start();
    }
}

当前线程:Thread-0
实现Runnable接口
/**
 * Created by 于占峰 on 2020/3/28/028.
 * 实现Runnable 实现run方法
 */
public class RunnableDemo implements Runnable {
    @Override
    public void run() {
        System.out.println("当前线程:"+Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        //实例化该类
        RunnableDemo runnableDemo = new RunnableDemo();
        //创建线程 并将类作为参数传入
        Thread thread = new Thread(runnableDemo);
        //调用thread的start方法
        thread.start();
    }
}

当前线程:Thread-0
实现Callable接口
/**
 * Created by 于占峰 on 2020/3/28/028.
 * 实现Callable<?>接口 指定需要的返回值参数
 */
public class CallableDemo implements Callable<String> {
    @Override
    public String call() throws Exception {
        System.out.println("当前线程:"+Thread.currentThread().getName());
        return "Hell Callable";
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //构建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        //调用submit 传入实现类 返回 Future
        Future<String> future = executorService.submit(new CallableDemo());
        //future.get() 拿到线程的返回值 future.get()是一个阻塞方法 只有线程返回结果后才会执行
        System.out.println(future.get());
    }
}


当前线程:pool-1-thread-1
Hell Callable

四.JAVA线程的生命周期

java线程从创建到销毁,一共可能经历6种状态
NEW: 初始状态,线程被构建,但是还没有调用start的方法
RUNNABLED: 运行状态,JAVA线程把操作系统中就绪和运行两种状态统一称为”运 行中”
BLOCKED: 阻塞状态,表示线程进入等待状态,也就是线程因为某种原因放弃了CPU 的使用权,阻塞也分为几种情况
WAITING: 等待状态
TIME_WAITING: 超时等待状态,超时以后自动返回
TERMINATED: 终止状态,表示当前线程执行完毕
public class ThreadStatusDemo {

    public static void main(String[] args) {
        //TIME_WAITING
        new Thread(()->{
            while (true){
                try {
                    TimeUnit.SECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"Time_Wating_Demo").start();

        //WATING
        new Thread(()->{
            while (true){
                synchronized (ThreadStatusDemo.class){
                    try {
                        ThreadStatusDemo.class.wait();//等待阻塞
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Waiting").start();

        new Thread(new BlockedDemo(),"Blocked_Demo_1").start();
        new Thread(new BlockedDemo(),"Blocked_Demo_2").start();
    }

    static  class BlockedDemo extends Thread{
        public void run(){
            synchronized (BlockedDemo.class){
                while (true){
                    try {
                        TimeUnit.SECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

idea 中找到target目录下的该类class文件 右键 open in terminal 命令行输入 jps 查看运行的进程id 命令行输入 jstack 进程id 查看运行日志 可以查看到线程的运行状态日志