首页 > 其他分享 >线程池|多线程

线程池|多线程

时间:2023-09-11 19:13:31浏览次数:31  
标签:执行 销毁 run 创建 任务 线程 多线程

什么是线程池?

线程的引入是因为进程的花销很大,线程相较于进程的花销少了很多,但是随着并发程度提高,对性能的要求也提高,频繁的创建线程,销毁线程的开销似乎也挺大的,这种情况下,要想提高效率,就可以使用线程池来降低创建线程销毁线程的开销。线程池就是事先将需要的线程创建好,放到“池”中,需要线程的时候,直接从“池”里拿,用完之后又放回去。从“池”里获取线程和用完放回池里这两个操作是比创建销毁线程更高效的。创建线程销毁线程是交给操作内核来做的,而线程池是可以用代码就可以实现的,不必交给操作内核。

Java标准库中的线程池

上述newFixedThreadPool中,“new”是方法名字的一部分,不是new关键字。

 这里是使用Executors类中的newFixedThreadPool静态方法直接构造出一个对象来,相当于是把new操作隐藏到这个方法里了。我们把使用某个类的某个静态方法直接构造出对象的方法称为“工厂方法”,提供“工厂方法”的类称为“工厂类”,使用了“工厂类”的代码认为是使用了“工厂模式 ”。

上述代码创建了10 个线程,接下来可以给线程派活了。线程池中有一个重要的方法sumbit,给线程池提交若干个任务。

public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        for(int i = 0;i < 1000;i++){
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello"+" "+i);
                }
            });
        }
    }

线程池的工作模式可以认为是每个线程都派发了任务,当线程执行完任务之后,又可以去领取任务,由于每个线程执行任务的时间都是差不多的,因此可以认为每个线程执行任务的数量都差不多。进一步可以认为任务就在队列里中排队,线程依次来取任务,取一个执行一个,执行完了之后又去取下一个任务,如此循环直到任务执行完。

上述代码还涉及到变量捕获问题,i是主线程里的局部变量,随着主线程的代码执行结束就销毁了,可能主线程的for已经执行完了,当前run的任务在线程里还没排到,i就被销毁了。

 run方法是属于Runnable,它的执行不是立刻马上,而是在队列中排到它了,就让对应的线程去执行。为了避免作用域的差异,可能run执行的时候,i已经销毁了,所以就有了变量捕获,就是让run方法将主线程上的i给拷贝一份在run的栈上。修改的代码如下:

public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        for(int i = 0;i < 1000;i++){
            int n = i;
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("hello"+" "+n);
                }
            });
        }
    }

Executors 提供了四个线程池:

1、newFixedThreadPool:创建固定大小的线程池,能够控制最大并发数,超出的线程会在LinkedBlockingQueue阻塞队列中等待;

2、newCAchedThredPool:创建线程数目动态增长的线程池;

3、newSingleThredPool:创建只有一个线程的线程池;

4、newSchdeuledThredPool:可以指定一段时间后执行命令,类似于定时器。

Executors本质上是ThreadPoolExecutor的类的封装。

ThreadPoolExecutor参数介绍

 

 corePoolSize表示核心线程数,当线程池创建的线程数小于核心线程数时,即便此时创建的线程数有空闲的,也会创建一个新的线程来执行任务,直到线程数大于等于核心线程数,再根据是否有空闲线程来决定要不要创建新的线程。

maximumPoolSize表示最大线程数,即允许创建的最大线程数。

keepAliveTime,当创建的线程数大于核心线程数的时候,当线程的空闲时间超过了keepAliveTime,则空闲的线程就会被销毁。

unit,线程存活时间的单位,从小到大:纳秒,微妙,毫秒,秒,分,小时,天。

workQueue,存储任务的阻塞队列。

threadFactory,线程工厂,负责创建新的线程(提供线程的工厂)。

handler,线程饱和策略,当线程池和队列都满了,则表示线程池已经饱和。

 

标签:执行,销毁,run,创建,任务,线程,多线程
From: https://www.cnblogs.com/xbyss/p/17685655.html

相关文章

  • 详解Java多线程编程中线程的启动、中断或终止操作
    ​在Java中start和tun方法可用被用来启动线程,而用interrupt方法来中断或终止线程,以下我们就来详解Java多线程编程中线程的启动、中断或终止操作 线程启动: 1.start()和run()的区别说明start():它的作用是启动一个新线程,新线程会执行相应的run()方法。start()不能被......
  • Linux多线程同步机制(下)
    @TOC前言一、读写锁多线程同步机制中的读写锁(Read-WriteLock)是一种特殊的锁机制,用于控制对共享资源的读写访问。读写锁允许多个线程同时读取共享资源,但在写操作时需要独占访问。读写锁的基本原则是:多个线程可以同时获取读锁,但只有一个线程可以获取写锁。当有线程持有写锁时,其他线......
  • 多线程中的sleep和wait有什么区别
    多线程中的sleep和wait有什么区别在多线程中,sleep()和wait()是两种不同的方法,有以下区别:调用位置:sleep()是Thread类的静态方法,可以在任何地方调用;而wait()是Object类的方法,只能在同步代码块或同步方法中调用。锁的释放:sleep()方法不会释放锁,线程持有锁的状态不变;而wait()方......
  • 11 多线程实现聊天
    气死了,这个错误搞了半天!packageInternet;importjava.net.DatagramSocket;importjava.net.SocketException;publicclassTest11_Me{publicstaticvoidmain(String[]args)throwsException{newThread(newTest11_Send(205,"localhost",2000)).s......
  • JavaSE--多线程
    一、多线程1、进程与线程概念  进程是一个应用程序(1个进程是一个软件),一个进程可以启动多个线程  线程是一个进程中的执行场景/执行单元2、进程与线程的关系  a)进程与线程    进程可以看作是一个公司,线程就是公司中的一个小员工    进程A与进程B的内存独立不......
  • rust 多线程
    多线程之间的通信和内存共享常见方式usestd::sync::mpsc;usestd::thread;usestd::sync::{Arc,Mutex};structUser{name:String}fnmain(){//Arc通过共享内存在线程间通信数据不可修改(所以这里使用的不可变引用)letusr_raw=Arc::new(User{......
  • 项目八股[线程池]
    为什么要有线程池因为频繁创建线程再销毁线程回收所有资源开销很大,所以项目中实现了一个线程池,线程池需要的做的事情就是维护任务队列与线程回调函数,工作线程即使在没有任务的情况下也不应该被回收,而是应该挂起等待唤醒。所以总结一下要点:1.线程池的实现和初始化:1.任务如何提......
  • 12分钟从Executor自顶向下彻底搞懂线程池
    前言上篇文章13分钟聊聊并发包中常用同步组件并手写一个自定义同步组件聊到并发包中常用的同步组件,并且还手把手实现了自定义的同步组件本篇文章来聊聊并发包下的另一个核心-线程池阅读本文大概12分钟通读本篇文章前先来看看几个问题,看看你是否以及理解线程池什么是池化技......
  • 27 线程池
    packageThreadDemo;importjava.lang.reflect.Executable;importjava.util.concurrent.Executor;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;//线程池publicclassTest27_Pool{publicstaticvoidmain(String[]ar......
  • C++多线程编程:包括多线程打印ABC、线程池实现等等
    #include<iostream>#include<thread>#include<mutex>#include<condition_variable>std::condition_variablecond;std::mutexprint_mutex;intflag=0;voidprint_thread(intnum){for(inti=0;i<10;i++)//循环{......