Detailed explanation of the use of scheduled task ScheduledThreadPoolExecutor

Detailed explanation of the use of scheduled task ScheduledThreadPoolExecutor

In the short time ago, a timer was needed to process the data received by the Bluetooth device, and the processing frequency was very fast, so a stable timer was needed to ensure the long-term progress of the data. The ScheduledThreadPoolExecutor class is a good choice.

Under normal circumstances, we use the Timer and TimerTask classes for timers to complete timing tasks, and set the extension time and cycle time interval.
ScheduledThreadPoolExecutor can also complete timing tasks like Timer, and the time interval is more accurate.

Error description:

Let me check in the background program that the Timer execution program may be delayed by 1 or 2 milliseconds. If it is a task that is executed once a second, it may be delayed by 60 milliseconds in one minute, and 3600 milliseconds in one hour, which is equivalent to 3 seconds. The actual user sees Make no difference.
However, if my program needs to execute a task every 40 milliseconds, if there is still an error of 1 or 2 milliseconds, there will be an error of 25 milliseconds in 1 second, and there will be an error of 1 second in about 40 seconds, and there will be an error of more than ten minutes. An error of more than ten seconds is a very serious delay for UI display.
And I use ScheduledThreadPoolExecutor to do tasks at intervals of 40 milliseconds. Generally, there is an error of more than 1 second in more than ten minutes, which is still acceptable.
This is why I use the ScheduledThreadPoolExecutor class.

Introduction to ScheduledThreadPoolExecutor

A ScheduledThreadPoolExecutor that can alternatively be scheduled to run commands after a given delay, or periodically. This class is preferred over Timer when multiple worker threads are required, or when additional flexibility or functionality of the ThreadPoolExecutor is required.

There are some drawbacks to using Timer and TimerTask:

1. Timer only creates one thread. When your task execution time exceeds the set delay time will cause some problems.

2. The thread created by Timer does not handle exceptions, so once an unchecked exception is thrown, the thread will terminate immediately.

It is recommended to use ScheduledThreadPoolExecutor after JDK 5.0. This class belongs to the Executor Framework. In addition to handling exceptions, it can also create multiple threads to solve the above problems.

Use of Timer and TimerTask

Everyone should be able to use this, but let me show you the code:

        Timer  timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                log.e("time:");

            }
        }, 2000, 40);//2000表示第一次执行任务延迟时间,40表示以后每隔多长时间执行一次run里面的任务

Use of ScheduledThreadPoolExecutor

Learn how to use it first and then explore it in depth.

        ScheduledThreadPoolExecutor  scheduled = new ScheduledThreadPoolExecutor(2);
        scheduled.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                loge("time:");
            }
        }, 0, 40, TimeUnit.MILLISECONDS);//0表示首次执行任务的延迟时间,40表示每次执行任务的间隔时间,TimeUnit.MILLISECONDS执行的时间间隔数值单位

Interval unit millisecond: TimeUnit.MILLISECONDS
Interval unit second: TimeUnit.SECONDS
Interval unit minute: TimeUnit.MINUTES
Interval unit hour: TimeUnit.HOURS
Interval unit day: TimeUnit.DAYS

An instance of a timer

A timer that displays seconds using Timer and TimerTask, ScheduledThreadPoolExecutor

Effect:

1
It seems that the UI is refreshed every second, but in order to see the delay effect of 40 milliseconds, the index is added every 40 milliseconds. After adding 25 times, the UI is refreshed once. On the surface, it seems to be the same as the effect of refreshing every second.

code:

package com.example.wenzhi.scheduledthreadpoolexecutordemo;

import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MainActivity extends AppCompatActivity {
    
    

    TextView tv_time;
    int      time;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_time = (TextView) findViewById(R.id.tv_time);

    }

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (time % 25 == 0) {
                tv_time.setText("" + time / 25);
            }
        }
    };

    /**
     * 普通定时器
     */
    Timer timer;

    public void timer(View view) {
        stopTimer1();
        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                loge("time:" + time++);//add
                handler.sendEmptyMessage(11);
            }
        }, 2000, 40);
    }

    public void stop(View view) {
        stopTimer1();
    }

    /**
     * 停止定时器
     */
    private void stopTimer1() {
        if (timer != null) {
            timer.cancel();
            timer = null;
        }
    }


    /**
     * 稳定的定时器
     */
    ScheduledThreadPoolExecutor scheduled;

    public void timer2(View view) {
        stopTimer2();
        scheduled = new ScheduledThreadPoolExecutor(2);
        scheduled.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                loge("time:" + time++);
                handler.sendEmptyMessage(11);
            }
        }, 0, 40, TimeUnit.MILLISECONDS);

    }

    public void stop2(View view) {
        stopTimer2();
    }

    /**
     * 停止定时器
     */
    private void stopTimer2() {
        if (scheduled != null) {
            scheduled.shutdownNow();
            scheduled = null;
        }
    }

    private void loge(String msg) {
        Log.e("TAG", msg);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        System.exit(0);
    }

    /**
     * 数据清零
     */
    public void clear(View view) {
        time = 0;
        tv_time.setText("" + time);
    }

}

Log data comparison

Timer timer

11-29 01:08:09.940 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:0
11-29 01:08:09.980 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:1
11-29 01:08:10.020 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:2
11-29 01:08:10.060 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:3
11-29 01:08:10.100 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:4
11-29 01:08:10.140 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:5
11-29 01:08:10.180 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:6
11-29 01:08:10.224 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:7
11-29 01:08:10.264 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:8
11-29 01:08:10.304 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:9
11-29 01:08:10.344 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:10
11-29 01:08:10.384 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:11
11-29 01:08:10.424 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:12
11-29 01:08:10.468 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:13
11-29 01:08:10.508 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:14
11-29 01:08:10.548 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:15
11-29 01:08:10.592 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:16
11-29 01:08:10.632 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:17
11-29 01:08:10.672 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:18
11-29 01:08:10.712 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:19
11-29 01:08:10.752 6070-20203/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:20

It can be seen that the above time interval is not very stable, and some of them are more than 40 milliseconds apart

ScheduledThreadPoolExecutorTimer

11-29 01:11:13.492 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:0
11-29 01:11:13.528 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:1
11-29 01:11:13.564 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:2
11-29 01:11:13.604 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:3
11-29 01:11:13.644 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:4
11-29 01:11:13.684 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:5
11-29 01:11:13.724 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:6
11-29 01:11:13.764 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:7
11-29 01:11:13.804 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:8
11-29 01:11:13.844 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:9
11-29 01:11:13.888 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:10
11-29 01:11:13.924 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:11
11-29 01:11:13.984 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:12
11-29 01:11:14.004 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:13
11-29 01:11:14.044 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:14
11-29 01:11:14.084 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:15
11-29 01:11:14.124 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:16
11-29 01:11:14.164 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:17
11-29 01:11:14.204 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:18
11-29 01:11:14.244 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:19
11-29 01:11:14.284 6070-22987/com.example.wenzhi.scheduledthreadpoolexecutordemo E/TAG: time:20

It can be seen that except for the first and second data above, the other data are very stable, and the interval time is 40 milliseconds.

And the longer the time, the more you can see the gap between the two timers.

Mutual Encouragement: When your ambition can't support your dream, it's time to work hard

Guess you like

Origin blog.csdn.net/wenzhi20102321/article/details/78681379