• Java线程池学习


    一、实现Java多线程的方法

    1、继承Thread类创建多线程

    Thread类本质实现了Runnable接口。启动线程为start0()方法。是个native方法。

     1 public class ThreadProcess extends Thread {
     2 
     3     @Override
     4     public void run(){
     5         long lastTime = System.currentTimeMillis();
     6         for(int i = 0; i < 1; i++){
     7             int ele = Integer.MAX_VALUE;
     8             while (ele >= 0){
     9                 int ele2 = ele - Integer.MAX_VALUE + 65535 - 37666 + 44443;
    10                 int temp = Math.max(ele2, ele);
    11                 if(temp != ele){
    12                     temp = ele;
    13                 }
    14                 ele = temp-1;
    15             }
    16         }
    17         System.out.println("Time cost from thread " + (System.currentTimeMillis() -  lastTime));
    18     }
    19 }

    2、实现Runnable。一个类已经继承了Thread类就无法继承其它类。

     1 class AccountOperator implements Runnable {
     2     private int count;
     3     private final byte[] lock = new byte[0];
     4 
     5     public AccountOperator() {
     6         this.count = 0;
     7     }
     8 
     9     public void run() {
    10         synchronized (lock) {
    11             count++;
    12             System.out.println(Thread.currentThread().getName() + ":" + count);
    13         }
    14     }
    15 }

    3、实现Callable

    如果运行完线程并且需要线程返回结果的时候,可以

     1 import java.util.concurrent.Callable;
     2 
     3 public class GetDataThread<V> implements Callable<V> {
     4     private V v;
     5 
     6     public GetDataThread(V v) {
     7         this.v = v;
     8     }
     9 
    10     @Override
    11     public V call() {
    12         return this.v;
    13     }
    14 }
     1 public class Main {
     2     public static void main(String[] args) throws Exception{
     3         String data = "data";
     4         FutureTask<String> ft = new FutureTask<>(new GetDataCal<>(data));
     5         Thread t = new Thread(ft);
     6         t.start();
     7         String res = ft.get();
     8         System.out.println("Result: " + res);
     9     }
    10 }

    二、Java线程池

    线程的创建和销毁是需要时间的。记线程创建的时间为T1, 线程运行的时间为T2,线程销毁的时间为T3。如果T1 + T3 远远大于 T2,并且有很多这样的任务需要并行执行时,就可以使用线程池。

    因为通过线程池,线程资源可以重复使用。

    1、常见的线程池

    • newSingleThreadExecutor:创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行
    • newFixedThreadExecutor:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    • newCachedThreadExecutor:  创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程可以无限创建。
    • newScheduleThreadExecutor:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

    2、首先看下ThreadPoolExecutor方法。构造函数包含了几个重要参数,

    1     public ThreadPoolExecutor(int corePoolSize,
    2                               int maximumPoolSize,
    3                               long keepAliveTime,
    4                               TimeUnit unit,
    5                               BlockingQueue<Runnable> workQueue
    6                               RejectedExecutionHandler handler){}
    1. corePoolSize, 线程池核心线程数量
    2. maximumPoolSize,线程池最大线程数
    3. keepAliveTime,当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
    4. unit  存活时间的单位
    5. workQueue  存放任务的队列
    6. handler  超出线程范围和队列容量的任务的处理程序,也叫拒绝策略。

    3、先看下线程池的实现原理

    提交一个任务到线程池,线程池的处理流程如下

    • 判断核心线程池是否都在执行任务,如果不是,则创建新的线程执行任务
    • 若核心线程都在执行任务,判断工作队列满没满,如果没满,把任务提交给队列
    • 若队列满了,判断线程池里的线程是否都处于工作状态。如果没有,则创建一个新的工作线程来执行任务,如果满了则交给拒绝策略处理
    谢谢!
  • 相关阅读:
    node 跨域请求设置
    iOS下如何阻止橡皮筋效果
    您的手机上未安装应用程序 android 点击快捷方式提示未安装程序的解决
    您的手机上未安装应用程序 android 点击快捷方式提示未安装程序的解决
    ImageButton的坑 ImageButton 有问题
    ImageButton的坑 ImageButton 有问题
    ImageButton的坑 ImageButton 有问题
    textView代码设置文字居中失效 textView设置文字居中两种方法
    textView代码设置文字居中失效 textView设置文字居中两种方法
    textView代码设置文字居中失效 textView设置文字居中两种方法
  • 原文地址:https://www.cnblogs.com/ylxn/p/10354551.html
Copyright © 2020-2023  润新知