java多线程
  dxvtvaa1pJOm 2023年12月15日 23 0

一、多线程的概念

  • 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。
  • 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
  • 一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
  • 多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

二、线程的生命周期

java多线程_线程池

java多线程_多线程_02

三、创建线程的三种方式

1、继承 Thread 类

class TestThread extends Thread{
    private Thread t;
    private String threadName;
 
    TestThread( String name) {
        threadName = name;
        System.out.println("Creating " +  threadName );
    }
    @Override
    public void run() {
        System.out.println("Running " +  threadName );
        try {
            for(int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                // 让线程睡眠一会
                Thread.sleep(50);
            }
        }catch (InterruptedException e) {
            System.out.println("Thread " +  threadName + " interrupted.");
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }
    @Override
    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }
}
 
public class ThreadDemo  {
 
    public static void main(String args[]) {
        TestThread T1 = new TestThread( "Thread-1");
        T1.start();
 
        TestThread T2 = new TestThread( "Thread-2");
        T2.start();
    }
}

2、实现Runnable接口

class TestRunnable implements Runnable{
    private Thread t;
    private String threadName;
 
    TestRunnable( String name) {
        threadName = name;
        System.out.println("Creating " +  threadName );
    }
 
    @Override
    public void run() {
        System.out.println("Running " +  threadName );
        try {
            for(int i = 4; i > 0; i--) {
                System.out.println("Thread: " + threadName + ", " + i);
                // 让线程睡眠一会
                Thread.sleep(50);
            }
        }catch (InterruptedException e) {
            System.out.println("Thread " +  threadName + " interrupted.");
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }
 
    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }
}
 
 
 
 
public class  RunableDemo{
 
    public static void main(String args[]) {
        TestRunnable R1 = new TestRunnable( "Thread-1");
        R1.start();
 
        TestRunnable R2 = new TestRunnable( "Thread-2");
        R2.start();
    }
}

3、实现Callable接口

public class CallableThreadTest implements Callable<Integer> {
    public static void main(String[] args) {
        CallableThreadTest ctt = new CallableThreadTest();
        FutureTask<Integer> ft = new FutureTask<>(ctt);
        for(int i = 0;i < 100;i++) {
            System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);
            if(i==20) {
                new Thread(ft,"有返回值的线程").start();
            }
        }
        try {
            System.out.println("子线程的返回值:"+ft.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
 
    }
    @Override
    public Integer call() throws Exception {
        int i = 0;
        for(;i<100;i++) {
            System.out.println(Thread.currentThread().getName()+" "+i);
        }
        return i;
    }
}

四、线程池

为什么使用线程池

  1. 降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。
  2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
  3. 提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控

ThreadPoolExecutor线程池类参数详解

参数

说明

workQueue

线程池所使用的任务缓冲队列

unit

keepAliveTime的单位,TimeUnit中的几个静态属性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS

threadFactory

线程工厂,用于创建线程,一般用默认的即可

maximumPoolSize

线程池维护线程的最大数量

keepAliveTime

线程池除核心线程外的其他线程的最长空闲时间,超过该时间的空闲线程会被销毁

handler

线程池对拒绝任务的处理策略

corePoolSize

核心线程数量,线程池维护线程的最少数量

当线程池任务处理不过来的时候,可以通过handler指定的策略进行处理,ThreadPoolExecutor提供了四种策略

  1. ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常;也是默认的处理方式。
  2. ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

线程池任务执行

添加执行任务
  • submit() 该方法返回一个Future对象,可执行带返回值的线程;或者执行想随时可以取消的线程。Future对象的get()方法获取返回值。Future对象的cancel(true/false)取消任务,未开始或已完成返回false,参数表示是否中断执行中的线程
  • execute() 没有返回值。
线程池任务提交过程

java多线程_线程池_03

  1. 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
  2. 如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,那么任务被放入缓冲队列。
  3. 如果此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
  4. 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
  5. 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

总结即:处理任务判断的优先级为 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。

线程池关闭
  1. shutdown() 不接收新任务,会处理已添加任务
  2. shutdownNow() 不接受新任务,不处理已添加任务,中断正在处理的任务
常见队列
  1. ArrayBlockingQueue: 这是一个由数组实现的容量固定的有界阻塞队列.
  2. SynchronousQueue: 没有容量,不能缓存数据;每个put必须等待一个take; offer()的时候如果没有另一个线程在poll()或者take()的话返回false。
  3. LinkedBlockingQueue: 这是一个由单链表实现的默认无界的阻塞队列。LinkedBlockingQueue提供了一个可选有界的构造函数,而在未指明容量时,容量默认为Integer.MAX_VALUE。

Executors线程工厂类

  1. Executors.newCachedThreadPool();
    说明: 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.
    内部实现:new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue());
  2. Executors.newFixedThreadPool(int);
    说明: 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
    内部实现:new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue());
  3. Executors.newSingleThreadExecutor();
    说明:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照顺序执行。
    内部实现:new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue())
  4. Executors.newScheduledThreadPool(int);
    说明:创建一个定长线程池,支持定时及周期性任务执行。
    内部实现:new ScheduledThreadPoolExecutor(corePoolSize)
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年12月15日 0

暂无评论

dxvtvaa1pJOm
作者其他文章 更多

2023-12-15