Android开发中的多线程

Android进阶——性能优化之多线程总结及简单应用(一) 进程是一个正在执行中的程序,线程在控制着进程的执行。线程属于某个进程,进程中的多个线程共享进程的内存。CPU真正执行的是线程,在某一时刻永远只有一个线程在执行(多核除外),cpu总是在极短的时间内不停地切换线程,但因切换时间极短根本感受不到,这也是在线程里sleep的原因之一,尤其是当需要快速对用户交互操作响应的时,譬如网络操作、IO操作、大数据量的计算等耗时操作都应该放到其他线程。合理使用多线程有利于提高用户体验。 阅读详情

Android开发中的多线程

多线程案例——计时器

这个案例中,屏幕启动之后,进入如图所示的界面。

屏幕上有一个文本框用于显示逝去的时间,此外还有一个“停止计时”按钮。案例的用例图如图所示。

能够在屏幕上“实时地显示”时间的流逝,单线程程序是无法实现的,必须要多线程程序才可以实现,即便有些计算机语言可以通过封装好的类实现这一功能,但从本质上讲这些封装好的类就是封装了一个线程。

综上所述,完成本案例用到的知识及技术如下:

  1)进程和线程的概念;

  2)Java中的线程,在Java中创建线程的方式;

  3)Android中的线程,包括:Message、Handler、Looper和HandlerThread等概念。

线程究竟是什么?在Windows操作系统出现之前,个人计算机上的操作系统都是单任务系统,只有在大型计算机上才具有多任务和分时设计。Windows、Linux操作系统的出现,把原本只在大型计算机才具有的优点,带到了个人计算机系统中。

进程概念

  一般可以在同一时间内执行多个程序的操作系统都有进程的概念。一个进程就是一个执行中的程序,而每一个进程都有自己独立的一块内存空间、一组系统资源。在进程的概念中,每一个进程的内部数据和状态都是完全独立的。在Windows操作系统下我们可以通过〈Ctrl+Alt+Del〉组合键查看进程,在UNIX和Linux操作系统下是通过PS命令查看进程的。打开Windows当前运行的进程,如图所示。

在Windows操作系统中一个进程就是一个exe或dll程序,它们相互独立,互相也可以通信,在Android操作系统中进程间的通信应用也是很多的。

线程概念

  多线程指的是在单个程序中可以同时运行多个不同的线程,执行不同的任务。多线程意味着一个程序的多行语句可以看上去几乎在同一时间内同时运行。

  线程与进程相似,是一段完成某个特定功能的代码,是程序中单个顺序的流控制。但与进程不同的是,同类的多个线程共享一块内存空间和一组系统资源,所以系统在各个线程之间切换时,资源占用要比进程小得多,正因如此,线程也被称为轻量级进程。一个进程中可以包含多个线程。图所示是计时器程序进程和线程之间的关系,主线程负责管理子线程,即子线程的启动、挂起、停止等操作。

 

Java中的线程

  Java的线程类是java.lang.Thread类。当生成一个Thread类的对象之后,一个新的线程就产生了。Java中每个线程都是通过某个特定Thread对象的方法run()来完成其操作的,方法run( )称为线程体。

  下面是构建线程类几种常用的方法:

  public Thread()

  public Thread(Runnable target)

  public Thread(Runnable target, String name)

  public Thread(String name)

  参数target是一个实现Runnable接口的实例,它的作用是实现线程体的run()方法。目标target可为null,表示由本身实例来执行线程。name参数指定线程名字,但没有指定的构造方法,线程的名字是JVM分配的,例如JVM指定为thread-1、thread-2等名字。

1、Java中的实现线程体方式1

  在Java中有两种方法实现线程体:一是继承线程类Thread,二是实现接口Runnable。下面我们先看看继承线程类Thread方式。

如果采用第1种方式,它继承线程类Thread并重写其中的方法 run(),在初始化这个类实例的时候,目标target可为null,表示由本实例来执行线程体。由于Java只支持单重继承,用这种方法定义的类不能再继承其他父类,例如代码清单如图:

复制代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class textThread extends Thread {
    boolean flag = true;
    int timer = 0;

    @Override
    public void run() {
        super.run();
        try {
            while (flag) {
                this.currentThread().sleep(1000);
                timer++;
                System.out.print(timer);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        textThread thread = new textThread();
        thread.start();
        System.out.print("启动计时器...");
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    
        try {
            String line = reader.readLine();
            if(line.equalsIgnoreCase("1")){
                //thread.stop();
                thread.flag = false;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
复制代码

在main主方法中通过new textThread()创建子线程,并通过thread.start()方法启动子线程,main主方法所在线程为主线程,主线程负责管理其他的子线程。本例进程、主线程和子线程之间的关系如图所示。

  子线程启动之后就开始调用run()方法,run()是一个线程体,我们在子线程中处理事情就是在这里编写代码实现的。本案例中子线程要做的事情就是:休眠1s,计时器加1,再反复执行。Thread.currentThread().sleep(1000)就是休眠1s。

  为了能够停止线程,我们在主线程中增加了一个标识,通过在控制台输入一个字符

  “1”来改变该标识t1.isRunning = false,从而结束这个线程。

注意:

  事实上线程中有一个stop()方法也可以停止线程,但是由于这种方法会产生线程死锁问题,所以在新版JDK中已经废止了,它的替代解决方法就是增加标识,就是我们在本例中采用的方案。

  很多人觉得线程难理解,主要有两个问题:

  线程休眠,既然线程已经休眠了,程序的运行速度还能提高吗?

  线程体一般都进行死循环,既然线程死循环,程序就应该死掉了,就会没有反应。

  1.关于线程休眠问题

  对线程休眠问题头痛的读者,其实还是在用单线程的思维模式考虑问题,多数情况下我们的PC都是单CPU的,某个时间点只能有一个线程运行。所谓多线程就是多个线程交替执行就好像同时运行似的。因此,休眠当前线程可以交出CPU控制权,让其他的线程有机会运行,多个线程之间只有交替运行效率才是最高的,这就像我们开车过十字路口,只有我等等,让你先过,你再等等让他先过,才能保证最高效率,否则就会造成交通系统崩溃,对线程情况也是一样的。因此,多线程中线程的休眠是程序运行的最有效方式。

  2.关于线程体死循环问题

  在单线程中如果是死循环,程序应就会死掉,没有反应,但是多线程中线程体(run方法)中的死循环,可以保证线程一直运行,如果不循环线程,则运行一次就停止了。在上面的例子中线程体运行死循环,可以保证线程一直运行,每次运行都休眠1s,然后唤醒,再然后把时间信息输出到控制台。所以,线程体死循环是保证子线程一直运行的前提。由于是子线程它不会堵塞主线程,就不会感觉到程序死掉了。但是需要注意的是有时我们确实执行一次线程体,就不需要循环了。

 程序运行后开始启动线程,线程启动后就计算逝去的时间,每过1s将结果输出到控制台。当输入1字符后线程停止,程序终止。如图所示。

Java中的实现线程体方式2

  上面介绍继承Thread方式实现线程体,下面介绍另一种方式,这种方式是提供一个实现接口Runnable的类作为一个线程的目标对象,构造线程时有两个带有Runnable target参数的构造方法:

  Thread(Runnable target);

  Thread(Runnable target, String name)。

  其中的target就是线程目标对象了,它是一个实现Runnable的类,在构造Thread类时候把目标对象(实现Runnable的类)传递给这个线程实例,由该目标对象(实现Runnable的类)提供线程体run()方法。这时候实现接口Runnable的类仍然可以继承其他父类。

请参看代码清单,这是一个Java AWT的窗体应用程序。

复制代码
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class textThread2 extends Frame implements Runnable, ActionListener {

    public Label label;
    public Button button;
    public Thread ClockThread;
    public boolean isRunning;
    public int timer = 0;

    public textThread2() {
        button = new Button("停止计时器");
        label = new Label("计算器启动");
        button.addActionListener(this);
        setLayout(new BorderLayout());
        add(button, "North");
        add(label, "Center");
        setSize(320, 480);
        setVisible(true);

        // textThread2 textThread2 = new textThread2();
        ClockThread = new Thread(this);
        ClockThread.start();
        isRunning = true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        isRunning = false;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try {
            while (isRunning) {
                Thread.currentThread().sleep(1000);
                timer++;
                label.setText("逝去了" + timer);
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        textThread2 textThread2 = new textThread2();
    }
}
复制代码

其中关于Java AWT知识就不在这里介绍了,有兴趣的读者可以自己看看相关书籍。在本例中构建AWT窗体的应用程序方式是继承Frame类。采用第1种方式——继承方式实现线程体是不可以的,因为Java是单继承的,这个类不能既继承Frame又继承Thread。应该采用第2种方式——实现Runnable接口方式。Runnable接口也有一个run()方法,它是实现线程体方法,其代码处理与上一节是一样。需要注意的是,在第2种方法中,创建了一个Thread成员变量clockThread,才用构造方法new Thread(this)创建一个线程对象,其中创建线程使用的构造方法是Thread(Runnable target),其中的this就是代表本实例,它是一个实现了Runnable接口的实现类。

程序运行结果如图所示,屏幕开始加载的时候线程启动开始计算时间,1s更新一次UI,当单击“结束计时”按钮时,停止计时。

Java中的实现线程体方式3

  实现线程体方式3是实现线程体方式2的变种,本质上还是实现线程体方式2,但是在Android应用开发中经常采用第3种方式。下面我们看第3种方式的计时器代码清单.

复制代码
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TextThread3 extends Frame implements ActionListener {

    private Button button;
    private Label label;
    private Thread clockThread;
    private int timer = 0;
    private boolean isRunning = true;

    public TextThread3() {
        button = new Button("停止计时");
        label = new Label("计时器开始。。。");
        button.addActionListener(this);
        setLayout(new BorderLayout());
        add(button, "North");
        add(label, "Center");
        setSize(320, 480);
        setVisible(true);

        clockThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (isRunning) {
                    try {
                        Thread.currentThread().sleep(1000);
                        timer ++;
                        label.setText("逝去了:"+timer);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        clockThread.start();
        isRunning = true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        isRunning = false;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        TextThread3 thread3 = new TextThread3();
    }
}
复制代码

与第2种方式比较,我们发现Frame类不再实现Runnable接口了,而是在实例化Thread类的时候,定义了一个实现Runnable接口的匿名内部类:

复制代码
clockThread = new Thread(new Runnable() {

            @Override
            public void run() {
                while (isRunning) {
                    try {
                        Thread.currentThread().sleep(1000);
                        timer ++;
                        label.setText("逝去了:"+timer);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
复制代码

有关Java多线程的内容还有很多,例如线程优先级、线程同步等,由于这些内容与本书关系不是很紧密,所以不再介绍了,有关其他的线程知识可以参考Java方面的书籍。接下来介绍一下Android中的线程。

Android中的线程

  在Android平台中多线程应用很广泛,在UI更新、游戏开发和耗时处理(网络通信等)等方面都需要多线程。Android线程涉及的技术有:Handler;Message;MessageQueue;Looper;HandlerThread。

  Android线程应用中的问题与分析

  为了介绍这些概念,我们把计时器的案例移植到Android系统上,按照在Frame方式修改之后的代码清单.

复制代码
package com.example.testthread4;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.*;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {

    private Button mButton;
    private TextView mTextView;
    private boolean isRunning = true;
    private Thread mThread;
    private int timer = 0;
    //private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mButton = (Button) findViewById(R.id.button1);
        mTextView = (TextView) findViewById(R.id.textView1);

        mButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                isRunning = false;
            }
        });
        /*handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 0:
                    mTextView.setText("逝去了:" + msg.obj);
                }
            }
        };*/
        mThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        /*Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);*/
                        mTextView.setText("逝去了:"+timer);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        mThread.start();
    }
}
复制代码

程序打包运行结果出现了异常,如图所示。

我们打开LogCat窗口,出错日志信息如图所示。

系统抛出的异常信息是“Only the original thread that created a view hierarchy can touch its views”,在Android中更新UI处理必须由创建它的线程更新,而不能在其他线程中更新。上面的错误原因就在于此。

  现在分析一下上面的案例,在上面的程序中有两个线程:一个主线程和一个子线程,它们的职责如图所示。

  由于labelTimer是一个UI控件,它是在主线程中创建的,但是它却在子线程中被更新了,更新操作在clockThread线程的run()方法中实现,代码如下:

复制代码
mThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        /*Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);*/
                        mTextView.setText("逝去了:"+timer);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
复制代码

这样的处理违背了Android多线程编程规则,系统会抛出异常“Only the original thread that created a view hierarchy can touch its views”。

  要解决这个问题,就要明确主线程和子线程的职责。主线程的职责是创建、显示和更新UI控件、处理UI事件、启动子线程、停止子线程;子线程的职责是计算逝去的时间和向主线程发出更新UI消息,而不是直接更新UI。

主线程的职责是显示UI控件、处理UI事件、启动子线程、停止子线程和更新UI,子线程的职责是计算逝去的时间和向主线程发出更新UI消息。但是新的问题又出现了:子线程和主线程如何发送消息、如何通信呢?

在Android中,线程有两个对象—消息(Message)和消息队列(MessageQueue)可以实现线程间的通信。下面再看看修改之后的代码清单.

复制代码
package com.example.testthread4;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.*;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {

    private Button mButton;
    private TextView mTextView;
    private boolean isRunning = true;
    private Thread mThread;
    private int timer = 0;
    private Handler handler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mButton = (Button) findViewById(R.id.button1);
        mTextView = (TextView) findViewById(R.id.textView1);

        mButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                isRunning = false;
            }
        });
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                case 0:
                    mTextView.setText("逝去了:" + msg.obj);
                }
            }
        };
        mThread = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        });
        mThread.start();
    }
}
复制代码

有的时候为了将Android代码变得更加紧凑,把线程的创建和启动编写在一条语句中,如下面

复制代码
        /*mThread = */new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (isRunning) {
                        Thread.currentThread().sleep(1000);
                        timer++;
                        Message message = new Message();
                        message.obj = timer;
                        message.what = 0;
                        handler.sendMessage(message);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }).start();
复制代码

运行模拟器结果如图8-1所示,加载屏幕后马上开始计时,也可以单击“停止计时”按钮来停止计时。

 


Android程序Crash时的异常上报 大家都知道,android应用不可避免的会发生crash,无论你的程序写的多完美,总是无法完全避免crash的发生,可能是由于android系统底层的bug,也可能是由于不充分的机型适配或者是糟糕的网络状况。当crash发生时,系统会kill掉你的程序,表现就是闪退或者程序已停止运行,这对用户来说是很不友好的,也是开发者所不愿意看到的,更糟糕的是,当用户发生了crash,开发者却无法得知程序为何crash,即便你想去解决这个crash,但是由于你无法知道用户当时的crash信息,所以你也无能为力。是否真的这样呢,其实android中有处理这类问题的方法。 立即下载

相关推荐

从零理解Brep:用Python玩转3D建模的边界表示法(附OpenCASCADE示例)

本文深入解析了边界表示法(Brep)在3D建模中的应用,通过Python和OpenCASCADE的实战示例,详细介绍了Brep的核心数据结构、布尔运算、网格转换及3D打印优化技巧。适合CAD设计、3D打印和计算机图形学领域的开发者学习与实践。

n4o5p6q7r的博客 429

全面详解Android实现多线程的几种方式(史上最全,最详细)

一、前言 Android多线程实现方式包括: 1、基础使用 继承Thread类 实现Runnable接口 Handler 2、复合使用 AsyncTask HandlerThread IntentService 3、高级使用 线程池(ThreadPool) 接下来对这几种实现多线程的方式进行全面 讲解。 二、基础使用 Android多线程实现的基础使用包括: 继承Thread类 实现Runnable接口 Handler 接下来对各个进行分析。 1、继承Thread类 1.1 简介

u013773608的博客 2万+

Virtuoso集成HspiceD:打通模拟设计全流程的仿真与PEX实战

本文详细介绍了Virtuoso集成HspiceD在模拟设计全流程中的应用,包括仿真与PEX实战。通过无缝衔接Virtuoso和HspiceD,设计师可以在同一环境中完成从原理图设计到PEX后仿真的全流程,大幅提升工作效率。文章还提供了仿真环境配置、前仿真关键设置、PEX全流程详解以及性能调优等实用技巧。

weixin_29271263的博客 97

Android开发中的多线程编程

多线程编程是Android开发中的一项重要技能。通过合理使用多线程,开发者可以提高应用的执行效率和响应速度。本文从多线程编程基础、实践、注意事项以及相关框架等方面详细阐述了Android开发中的多线程编程,希望对开发者有所帮助。在未来的Android开发中,多线程编程仍将是一个重要的研究方向。开发者需要不断学习和掌握新的多线程编程技术,以应对日益复杂的移动应用场景。同时,开发者也应关注线程安全和性能优化等方面的问题,以确保应用的稳定性和流畅性。

emilio15979289的博客 399

武汉理工大学数据结构综合实验——连连看游戏综合实践

文章目录实验目的主要仪器设备及耗材一、实验要求二、分析与设计(非线性结构)1.数据结构的设计2.核心算法设计一条直线消子两条直线消子三条直线消子初始化游戏地图搜寻路径提示和重排3.测试用例设计4.测试效果总结 实验目的 (1)线性结构实验目的 调研连连看游戏,了解连连看游戏的功能和规则等 掌握集成开发工具VS2019的使用和C++的基础编程 了解MFC框架 了解线性结构,掌握数组的遍历、消子和胜负判断等算法 了解企业软件开发过程,应用迭代开发思路进行项目开发,养成良好的编程习惯和培养软件工程化思维 .

mo_zhe的博客 7612

在MacBook上直接跑Windows Server 2022:一个开发者的真实踩坑与配置全记录

本文详细记录了在MacBook上原生运行Windows Server 2022的完整流程与优化技巧。通过Boot Camp实现非虚拟机安装,开发者可以充分利用Mac硬件性能,搭建高效的本地开发环境,特别适合需要测试跨平台应用和服务器功能的场景。文章涵盖驱动处理、分区策略、Docker配置等关键步骤,为技术极客提供实用指南。

weixin_42620913的博客 247

Android开发中的多线程编程技术

转自:http://software.intel.com/zh-cn/articles/android-0/?utm_campaign=优快云&utm_source=intel.youkuaiyun.com&utm_medium=Link&utm_content=%20intelandroid%20%e2%80%93%20duoxiancheng   ...

Jay Chang 207

DNS入侵检测 datacon2020

DNS入侵检测 datacon2020。

weixin_51491521的博客 523

转载Android开发中的多线程编程技术

Android开发中的多线程编程技术 转载自http://tech.it168.com/a2011/0922/1250/000001250289_all.shtml 2011年10月03日00:05 it168网站原创 作者:关东升 赵志荣 编辑:景保玉 评论:0条   【IT168技术】多线程这个令人生畏的“洪水猛兽”,很多人谈起多线程都心存畏惧。在Android开发过程中

OnePiece 867

Hyper-V显卡直通实战:手把手解决Windows 11虚拟机错误码43(附完整参数配置)

本文详细解析了在Windows 11 Hyper-V虚拟机中配置显卡直通时遭遇错误码43的根源,并提供了从环境检查、核心PowerShell命令(如Set-VMGpuPartitionAdapter)配置到虚拟机内驱动替换的完整实战解决方案,帮助用户彻底解决显卡驱动无法加载的问题。

weixin_29238147的博客 901

【鸿蒙南向开发】OpenHarmony音频驱动audio适配方案

这份鸿蒙(HarmonyOS NEXT)文档包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。

HarmonyOS_666的博客 4518

Android 开发中的多线程编程技术

多线程这个令人生畏的“洪水猛兽”,很多人谈起多线程都心存畏惧。在Android开发过程中,多线程真的很难吗?多线程程序的“麻烦”源于它很抽象、与单线程程序运行模式不同,但只要掌握了它们的区别,编写多线程程序就会很容易了。下面让我们集中精力开始学习吧!   多线程案例——计时器   我在给我的学生讲多线程的时候都会举一个计时器的案例,因为计时器案例是多线程的经典应用。   这个案例中,屏幕启动

基于英特尔®架构的 Android开发 中文博客 2万+

TypeError: XGBClassifier.fit() got an unexpected keyword argument ‘early_stopping_rounds‘ 解决方案

本文主要介绍了TypeError: XGBClassifier.fit() got an unexpected keyword argument 'early_stopping_rounds’解决方案,希望能对使用XGBoost的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 1万+

US Digital E5编码器深度解析:25种CPR分辨率选型与STM32实战

编码器是运动控制系统中不可或缺的反馈元件,它通过将机械转动转换为电信号,为控制器提供位置与速度信息。增量式编码器以其结构简单、响应快、成本适中,成为工业自动化与机器人领域的主流选择。其核心参数CPR(每转周期数)决定了测量分辨率,而借助A/B正交信号的四倍频处理,可进一步将精度提升四倍。在工程实践中,选用何种分辨率需综合电机转速、MCU处理能力及机械安装空间;STM32的定时器编码器模式可高效解码,配合M法或T法测速,能实现稳定闭环。这类方案广泛用于小型机器人关节、AGV驱动轮及自动化送料机构。本文以US

weixin_34245082的博客 323

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

通过计时器的案例开发过程探讨android开发中的多线程问题

通过计时器的案例开发过程探讨android开发中的多线程问题 完成计时器的应用开发需要了解以下基本内容:  1)进程和线程的概念  2)Java中的线程,在Java中创建线程的方式;  3)Android中的线程,包括:Message、Handler、Looper和HandlerThread等概念  进程概念  一般可以在同一时间内执行多个程序的操作系统都有进程的概念。一个进程就是一个执行中的程序...

qq_41453257的博客 377

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: Android设置Activity背景为透明style
下一篇: java当中的定时器的4种使用方式
It_BeeCoder
博客等级 码龄10年 967粉丝 238原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值