线程池的使用(二)

本文介绍Java中四种线程池的使用方法,包括newCachedThreadPool、newSingleThreadExecutor、newFixedThreadPool和newScheduledThreadPool。通过具体示例展示了线程池的基本操作及线程的启动、取消、关闭等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.概述

上一篇多线程使用(一)我们介绍了如何使用实现单个线程来完成任务,今天我们来看看多个线程工作的情况,也就是线程池。

二.原理

概念

Executors 提供四种线程池:
1)newCachedThreadPool 是一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute() 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。

2)newSingleThreadExecutor 创建是一个单线程池,也就是该线程池只有一个线程在工作,所有的任务是串行执行的,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它,此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

3)newFixedThreadPool 创建固定大小的线程池,每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小,线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

4)newScheduledThreadPool 创建一个大小无限的线程池,此线程池支持定时以及周期性执行任务的需求。

当我们使用Executors创建不同类型的线程执行器时,都会返回一个ExecutorService对象,这个对象提供了两个方法来关闭线程池:

  • shutdown
    不会立即的终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
  • shutdownNow
    立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。

我们用一个例子来看看每个线程执行器的效果,先看效果图
这里写图片描述

三.代码

public class MainActivity extends AppCompatActivity {

    private final int TYPE_MSG_RUN = 1001;
    private final int TYPE_MSG_DONE = 1002;

    private Thread thread;
    private ProgressBar progressBar3;
    private ProgressBar progressBar2;
    private ProgressBar progressBar1;
    private TextView tv_info1;
    private TextView tv_info2;
    private TextView tv_info3;
    private TextView tv_start1;
    private TextView tv_start2;
    private TextView tv_start3;
    private TextView tv_cancel1;
    private TextView tv_cancel2;
    private TextView tv_cancel3;
    private TextView tv_shut_now;
    private TextView tv_shut;
    private TextView tv_info;

    private ExecutorService pool = Executors.newCachedThreadPool();

    private Callable<Integer> callable1;
    private Future task1;
    private Callable<Integer> callable2;
    private Future task2;
    private Callable<Integer> callable3;
    private Future task3;

    private final int THREAD1_START = 1001;
    private final int THREAD2_START = 1002;
    private final int THREAD3_START = 1003;

    private int num1 = 0;
    private int num2 = 0;
    private int num3 = 0;

    private android.os.Handler handler = new android.os.Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case THREAD1_START:
                    tv_info1.setText("线程一: "+msg.arg1);
                    progressBar1.setProgress(msg.arg1);
                    break;
                case THREAD2_START:
                    tv_info2.setText("线程二: "+msg.arg1);
                    progressBar2.setProgress(msg.arg1);
                    break;
                case THREAD3_START:
                    tv_info3.setText("线程三: "+msg.arg1);
                    progressBar3.setProgress(msg.arg1);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initData();
        addListener();
    }
    public void initView(){
        tv_info1 = (TextView) findViewById(R.id.tv_info1);
        tv_info2 = (TextView) findViewById(R.id.tv_info2);
        tv_info3 = (TextView) findViewById(R.id.tv_info3);
        progressBar1 = (ProgressBar) findViewById(R.id.progressBar1);
        progressBar2 = (ProgressBar) findViewById(R.id.progressBar2);
        progressBar3 = (ProgressBar) findViewById(R.id.progressBar3);
        tv_start1 = (TextView) findViewById(R.id.tv_start1);
        tv_start2 = (TextView) findViewById(R.id.tv_start2);
        tv_start3 = (TextView) findViewById(R.id.tv_start3);
        tv_cancel1 = (TextView) findViewById(R.id.tv_cancel1);
        tv_cancel2 = (TextView) findViewById(R.id.tv_cancel2);
        tv_cancel3 = (TextView) findViewById(R.id.tv_cancel3);
        tv_shut = (TextView) findViewById(R.id.tv_shut_down);
        tv_shut_now = (TextView) findViewById(R.id.tv_shut_down_now);
        tv_info = (TextView) findViewById(R.id.tv_info);
    }
    public void initData(){
        progressBar1.setProgress(0);
        progressBar1.setMax(100);
        progressBar2.setProgress(0);
        progressBar2.setMax(100);
        progressBar3.setProgress(0);
        progressBar3.setMax(100);
    }
    public void addListener(){
        tv_start1.setOnClickListener(onClickListener);
        tv_start2.setOnClickListener(onClickListener);
        tv_start3.setOnClickListener(onClickListener);
        tv_cancel1.setOnClickListener(onClickListener);
        tv_cancel2.setOnClickListener(onClickListener);
        tv_cancel3.setOnClickListener(onClickListener);
        tv_shut .setOnClickListener(onClickListener);
        tv_shut_now.setOnClickListener(onClickListener);
    }
    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.tv_start1:
                    if(progressBar1.getProgress() == progressBar1.getMax()){
                        num1 = 0;
                    }
                    startThread1();
                    break;
                case R.id.tv_start2:
                    if(progressBar2.getProgress() == progressBar2.getMax()){
                        num2 = 0;
                    }
                    startThread2();
                    break;
                case R.id.tv_start3:
                    if(progressBar3.getProgress() == progressBar3.getMax()){
                        num3 = 0;
                    }
                    startThread3();
                    break;
                case R.id.tv_cancel1:
                    cancelTask(task1);
                    break;
                case R.id.tv_cancel2:
                    cancelTask(task2);
                    break;
                case R.id.tv_cancel3:
                    cancelTask(task3);
                    break;
                case R.id.tv_shut_down:
                    if(pool!=null&& !pool.isShutdown()){
                        pool.shutdown();
                    }
                    break;
                case R.id.tv_shut_down_now:
                    if(pool!=null&& !pool.isShutdown()){
                        pool.shutdownNow();
                    }
                    break;
            }
        }
    };

    public void sendMsg(int num,int what){
        Message msg = Message.obtain();
        msg.what = what;
        msg.arg1 = num;
        handler.sendMessage(msg);
    }

    public void startThread1(){
        if(task1!=null&&!task1.isDone()||pool.isShutdown()){
            return;
        }
        callable1 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                while (num1<100){
                    num1++;
                    sendMsg(num1,THREAD1_START);
                    Thread.sleep(100);
                }
                return 100;
            }
        };
        task1 = pool.submit(callable1);
    }
    public void startThread2(){
        if(task2!=null&&!task2.isDone()||pool.isShutdown()){
            return;
        }
        callable2 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                while (num2<100){
                    num2++;
                    sendMsg(num2,THREAD2_START);
                    Thread.sleep(100);
                }
                return 100;
            }
        };
        task2 = pool.submit(callable2);
    }
    public void startThread3(){
        if(task3!=null&&!task3.isDone()||pool.isShutdown()){
            return;
        }
        callable3 = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                while (num3<100){
                    num3++;
                    sendMsg(num3,THREAD3_START);
                    Thread.sleep(100);
                }
                return 100;
            }
        };
        //提交一个带有返回结果的任务,返回Future对象
        task3 = pool.submit(callable3);
    }
    public void cancelTask(Future<Integer> task){
        if (task != null && !pool.isShutdown()) {
            task.cancel(true);
        }
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_thread_pool,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.item_newCachedThreadPool:
                pool = Executors.newCachedThreadPool();
                tv_info.setText("当前线程池类型: newCachedThreadPool");
                break;
            case R.id.item_newFixedThreadPool:
                pool= Executors.newFixedThreadPool(2);
                tv_info.setText("当前线程池类型: newFixedThreadPool");
                break;
            case R.id.item_newScheduledThreadPool:
                pool = Executors.newScheduledThreadPool(1);
                tv_info.setText("当前线程池类型: newScheduledThreadPool");
                break;
            case R.id.item_newSingleThreadExecutor:
                pool = Executors.newSingleThreadExecutor();
                tv_info.setText("当前线程池类型: newSingleThreadExecutor");
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (pool != null && !pool.isShutdown()) {
            pool.shutdownNow();
        }
    }
}

最后给出源码下载地址
点此下载源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值