线程

1、什么是并发与并行

        要想学习多线程,必须先理解什么是并发与并行:
        并行:指两个或多个事件在同一时间点发生。
        并发:指两个或多个事件在同一个时间段内发生。

2、什么是进程、线程

2.1进程

        进程是正在运行的程序的实例。
        比如打开一个浏览器、打开一个word等操作,都会创建进程。

2.2线程

        进程是线程的容器,即一个进程可以同时并发运行多个线程;
        比如进程可以理解为医院,线程是挂号、就诊、缴费、拿药等业务活动。

        多线程:多个线程并发执行。

3、线程的创建

3.1继承Thread类

        第一步:创建自定义线程类

package com.hg.Thread.creat;

import java.util.Date;

public class MyThread extends Thread{

    //线程的业务

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("MyThread线程正在运行," + new Date().getTime());
        }
    }
}

        第二步:创建测试类

        注意:

        1.新建的线程不会自动开始运行,必须通过start()方法启动线程
        2.main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

package com.hg.Thread.creat;

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

public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new MyThread().run();//程序从上往下执行

        //自定义线程
        //new MyThread().start(); //启动线程,等待cpu资源
        //new Thread(new MyThread2()).start();
        FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
        new Thread(futureTask).start();

        //main线程
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程正在执行," + new Date().getTime());
        }
        System.out.println(futureTask.get());
    }
}

        问题:java是单继承的,此时MyThread只能extendsThread类

3.2实现Runnable接口

        第一步:创建自定义类实现Runnable接口

package com.hg.Thread.creat;

import java.util.Date;

public class MyThread2 implements Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("MyThread2线程正在运行:" + new Date().getTime());
        }
    }
}

        第二步:创建测试类

package com.hg.Thread.creat;

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

public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new MyThread().run();//程序从上往下执行

        //自定义线程
        //new MyThread().start(); //启动线程,等待cpu资源
        //new Thread(new MyThread2()).start();
        FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
        new Thread(futureTask).start();

        //main线程
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程正在执行," + new Date().getTime());
        }
        System.out.println(futureTask.get());
    }
}

        问题:

        1.没有返回值,不支持泛型的返回值
        2.不可以抛出异常

3.3实现Callable接口

        Callable需要使用FutureTask类帮助执行,FutureTask类结构如下:

        第一步:创建自定义类实现Callable接口

package com.hg.Thread.creat;

import java.util.Date;
import java.util.concurrent.Callable;

public class MyThread3 implements Callable<String> {
    @Override
    public String call() throws Exception {
        for (int i = 0; i < 10; i++) {
            System.out.println("MyThread3正在运行:" + new Date().getTime());
        }
        return "叶瞬光是我女朋友";
    }
}

        第二步:创建测试类

package com.hg.Thread.creat;

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

public class ThreadTest {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //new MyThread().run();//程序从上往下执行

        //自定义线程
        //new MyThread().start(); //启动线程,等待cpu资源
        //new Thread(new MyThread2()).start();
        FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
        new Thread(futureTask).start();

        //main线程
        for (int i = 0; i < 10; i++) {
            System.out.println("main线程正在执行," + new Date().getTime());
        }
        System.out.println(futureTask.get());
    }
}

        问题:频繁创建和销毁线程开销大

3.4线程池-ThreadPoolExecutor

线程池的核心概念:

        线程池本质上是一个管理线程的容器,它预先创建一定数量的线程,当有任务需要执行时,直接从池中取出空闲线程来执行任务,避免频繁创建和销毁线程(线程的创建/销毁需要消耗CPU、内存等资源)。

Java线程池的核心参数:

public ThreadPoolExecutor(
int corePoolSize,//核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//空闲存活时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler//拒绝策略
)

这几个参数的作用:

参数 作用
corePoolSize 核心线程数:线程池长期保持的线程数量(即使空闲也不会销毁,除非设置allowCoreThreadTimeOut
maximumPoolSize 最大线程数:线程池允许创建的最大线程数
keepAliveTime 空闲超时时间:非核心线程空闲超过该时间会被销毁
TimeUnit 时间单位
workQueue 任务队列:核心线程都在忙时,新任务会先放入队列等待
threadFactory 线程工厂:自定义线程的创建方式(如设置线程名、优先级)
RejectedExecutionHandler 拒绝策略:当任务数超过 “最大线程数 + 队列容量” 时,如何处理新任务(如抛异常、丢弃任务等)

创建线程池:

package com.hg.Thread.creat.homeWork;

import java.util.concurrent.*;

public class Work2 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {

        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                3,
                5,
                10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(2),
                new ThreadFactory() {
                    int count = 1;

                    @Override
                    public Thread newThread(Runnable r) {
                        Thread thread = new Thread(r);
                        thread.setName("MyThread-" + count++);
                        return thread;
                    }
                },
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        poolExecutor.execute(new Thread2(1,10,200));
        poolExecutor.execute(new Thread2(11,20,300));
        poolExecutor.execute(new Thread2(21,30,100));
        poolExecutor.shutdown();
        System.out.println("所有子线程已启动,主线程继续执行");

}

static class Thread2 implements Runnable {
    private Integer begin;
    private Integer end;
    private Integer millis;

    public Thread2(Integer begin, Integer end, Integer millis) {
        this.begin = begin;
        this.end = end;
        this.millis = millis;
    }

    @Override
    public void run() {
        for (int i = begin; i <= end; i++) {
            System.out.println(Thread.currentThread().getName() + ":" + i);
            try {
                Thread.sleep(millis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Executors工具类:

        Executors是JDK提供的一个线程池工具类(位于java.util.concurrent包下),它封装了
ThreadPoolExecutor的创建细节,提供了一系列静态工厂方法,让你可以快速创建各种类型的线程池,无需手动设置corePoolSize、workQueue等复杂参数。

package com.hg.Thread.creat;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyThread4 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 5; i++) {
            int taskNum = 1;
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    //Thread.currentThread().getName():获得当前线程名字
                    System.out.println(Thread.currentThread().getName() + "正在执行" + taskNum);
                    try {
                        Thread.sleep(1000); //线程休眠,阻塞1秒钟
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executorService.shutdown();
    }
}

4、Thread类的常用方法

4.1Thread类常用方法说明

4.2 join()方法

package com.hg.Thread.method;

public class JoinMethodTest {
    public static void main(String[] args) throws InterruptedException {
        JoinMethod joinMethod = new JoinMethod();
        joinMethod.setName("joinMethod");
        joinMethod.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            if (i == 2){
                joinMethod.join();
            }
        }
    }
}

class JoinMethod extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ": " + i);
        }
    }
}

4.3 sleep()方法

package com.hg.Thread.method;

public class SleepMethodTest {
    public static void main(String[] args) throws InterruptedException {
        Thread sleepMethod = new Thread(new SleepMethod());
        sleepMethod.setName("sleepMethod");
        sleepMethod.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            if (i == 2){
                Thread.sleep(100);
            }
        }
    }
}

class SleepMethod implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

4.4 yield()方法

package com.hg.Thread.method;

import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;

public class YieldMethodTest {
    public static void main(String[] args) {
        Thread yieldMethod = new Thread(new FutureTask<>(new YieldMethod()));
        yieldMethod.setName("YieldMethod");
        yieldMethod.start();

        Thread.currentThread().setName("主线程");
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

class YieldMethod implements Callable {

    @Override
    public Object call() throws Exception {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + ": " + i);
            if (i == 2){
                Thread.yield();
            }
        }
        return null;
    }
}
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐