Java线程(线程池、创建线程的第三种方法callable)

线程池

补充资料:Doug Lea (JCP组织的一人)对线程池部分贡献巨大

 

常用线程池的接口和类:

Executor:线程池的顶级接口

ExecutorService:线程池接口可用submit(Runnable Task)提交任务代码。包含:Shutdown;

Shutdownnow等

Executors工厂类:可以通过这一个方法得到一个线程池

NewFixedThreadPool(int n Thread):获取固定数量的线程池。参数:指线程池中线程的数量

NewCacheThreadPool()获取动态数量的线程池,无上限

 

对于ExecutorService:需关注实现类TheadPoolExecutor,SheduledThreadPoolExecutor

Executors:1.创建固定线程个数的线程池

2.创建缓存线程池,又任务多少来决定

3.创建单线程池

4.创建调度线程池  调度:周期、定时执行

 

在API中:

Shutdown:启动一次顺序关闭,执行以前提交的任务,但不接受新任务

ShutDownNow:试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表

 

代码示例1 固定线程个数:

复制代码
import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

 

public class Demo {

    public static void main(String[] args) {

//        1.创建固定线程个数的线程池

        ExecutorService es=Executors.newFixedThreadPool(4);

//        2.提交任务

        Runnable run=new Runnable() {

            private int ticket;

 

            @Override

            public void run() {

                while (true) {

                    if (ticket <= 0) {

                        break;

                    }

                    System.out.println(Thread.currentThread().getName() + "卖完第:" + ticket + "张票");

                    ticket--;

                }

            }

        };

//        3.提交任务

                for(int i=0;i<=4;i++) {

            es.submit(run);

        }

//        4.关闭线程池

        es.shutdown();

        }

}
复制代码

 

 

 

代码示例 2 可变线程个数,由任务决定

复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class Demo {
    public static void main(String[] args) {
//        1.创建固定线程个数的线程池
//        ExecutorService es=Executors.newFixedThreadPool(4);
        ExecutorService es2=Executors.newCachedThreadPool();
//        2.提交任务
        Runnable run=new Runnable() {
            private int ticket;
 
            @Override
            public void run() {
                while (true) {
                    if (ticket <= 0) {
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "卖完第:" + ticket + "张票");
                    ticket--;
                }
            }
        };
//        3.提交任务
                for(int i=0;i<=4;i++) {
            es2.submit(run);
        }
//        4.关闭线程池
        es2.shutdown();
        }
}
复制代码

 

注:提交任务数不一定是4.要具体看运行结果

 

Excutors的另外两种方法

3. ExecutorService e3=Executors.newSingleThreadExecutor();
4. ExecutorService e4=Executors.newScheduledThreadPool();

 

 

Callable接口

语法:

Public interface Callable<V>{public V call() throws Exception}

特点:有返回值;使用时需要先转化为任务后被Thread调用

 

代码示例:

复制代码
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
 
public class Demo02 {
    public static void main(String[] args) {
//        功能需求:计算1-100的和并使用Callable接口
        Callable<Integer> callable=new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                System.out.println(Thread.currentThread().getName()+"开始计算");
                int sum = 0;
                for (int j = 1;j<=100;j++){
                    sum+=j;
                    Thread.sleep(100);
                }
                return sum;
 
            }
        };
//        把Callable转化为可执行的任务
        FutureTask<Integer> task = new FutureTask<>(callable);
 
//        创建线程
        Thread thread = new Thread(task);
 
//        启动线程
        thread.start();
 
//        获取结果
        Integer sum= null;
        try {
            sum = task.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("结果是"+sum);
        }
}
复制代码

 

 

 

Callable与线程池的结合的使用

这种方法与线程池的配合更为紧密

优点:无需先转化为task,再进行执行

需求示例:使用Callable和线程池计算1-100的和

代码示例:

复制代码
import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

 

public class Demo03 {

    public static void main(String[] args) throws Exception {

//        1. 创建线程池

        ExecutorService es = Executors.newFixedThreadPool(1);

//        2.提交任务Future:表示将要执行任务的结果

        Future<Integer> future =  es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                System.out.println(Thread.currentThread().getName()+"开始计算");

                int sum=0;

                for (int i=0;i<=100;i++){

                    sum+=i;

                }

                return sum;

            }

        });

//        3.获取任务结果

       System.out.println(future.get());

 

//        4.关闭线程池

        es.shutdown();

    }

}
复制代码

 

 

 

 

Future接口

功能:表示将要完成的任务的结果

案例需求:使用两个线程,并发计算1-50和51-100的和,再进行汇总统计

Future.get()方法需要等待callable的方法执行完毕才可以继续执行,即 同步

关于同步、异步:我们现在手头有两个线程A\B,A在使用过程中会调用B线程。同步的含义是例如A需要执行三个部分,在第一个部分时调用了B,调用之后不继续执行第二个部分而是等待B被调用完之后再继续执行第二第三个部分。

异步的含义是,A执行第一部分并调用了B线程,A不继续等待B线程执行完而接着执行第二部分第三部分。

代码示例:

复制代码
import java.util.concurrent.Callable;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.Future;

 

public class Demo4 {

    public static void main(String[] args) throws Exception{

//        1.创建线程池

        ExecutorService es = Executors.newFixedThreadPool(2);

//        2.创建任务及对象

        Future<Integer> future =es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                int sum=0;

                for(int i=0;i<=50;i++){

                    sum+=i;

                }

                return sum;

            }

        });

 

        Future<Integer> future2=es.submit(new Callable<Integer>() {

            @Override

            public Integer call() throws Exception {

                int sum=0;

                for(int i=51;i<=100;i++){

                    sum+=i;

                }

                return sum;

            }

        });

//      3.获取结果

        int sum=future.get()+future2.get();

        System.out.println("结果是" + sum);

 

//        4.关闭线程

        es.shutdown();

    }

}
复制代码

 

posted @   逃逸线LinesOfFlight  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示