精华内容
下载资源
问答
  • Android应用层遵循单线程模型原则,在Activity被创建之时,会启用主线程(main),也就是UI线程。UI线程负责刷新UI界面和与UI相关的操作(控件监听、事件响应等)。由于Android的FC机制,主线程一旦被阻塞5s以上,则应用...

    Android

    应用层遵循单线程模型原则,在Activity被创建之时,会启用主线程(main),也就是UI线程。UI线程负责刷新UI界面和与UI相关的操作(控件监听、事件响应等)。由于Android的FC机制,主线程一旦被阻塞5s以上,则应用程序强制关闭。所以UI线程不能被阻塞,所以一些大量耗时的操作,必须放在后台线程运行。

    后台运行的线程一般有如下几个特点:耗时较长,消耗资源较多,并且不一定会有结果或者确切的返回值(例如读取大型图片、音乐,或者下载网络资源),如果放在UI线程之中,极易导致应用程序崩溃,或者造成长时间的黑屏,影响用户体验。

    创建后台线程的方法有多种,最近学到三种方法

    1、使用Android系统工具类 AsyncTask(Params,Progress,Result)

    AsyncTask是一个轻量级线程,三个泛型参数分别是

    Params传入参数,int型Progress为进度条进度,Result为返回值

    要使用AsyncTask,必须继承之并复写其中的几个重要的函数。

    onPreExecute(), 该方法将在执行实际的后台操作前被UI

    thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。

    doInBackground(Params...), 将在onPreExecute

    方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用

    publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。

    onProgressUpdate(Progress...),在publishProgress方法被调用后,UI

    thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。

    onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI

    thread调用,后台的计算结果将通过该方法传递到UI thread.

    注:Task必须在UI线程中创建,并调用并且只能调用一次execute方法,该方法的参数为传入的泛型Params。

    其余函数最好不要手动调用,容易造成线程崩溃。多次调用Task,容易造成线程池溢出。

    2、使用Handler和HandlerThread

    误区: Handler handler = new Handler ();

    handler.post(r);

    这种做法看似创建了一个线程,但实际上handler只是直接调用Runnable中的run()

    方法,而不执行线程的start()函数,所以这两句代码执行后,程序仍然在UI线程中执行。所以我们引入HandlerThread,因为HandlerThread中有一个Looper对象,用以循环消息队列。

    为了使用Looper,必须子类化Handler,并复写它的构造函数。

    class

    MyHandler

    extends Handler{

    public

    MyHandler() {}

    public

    MyHandler(Looper looper){

    super (looper);

    }

    public

    void

    handleMessage(Message msg){

    //....这里运行耗时的过程

    }

    }

    }

    handleMessage(Message msg)函数用以接收消息,msg则是从UI线程中发出的消息,可以传递各种对象,根据这些对象和数值进行操作。

    有了Handler子类,则可以在UI线程中进行创建和初始化

    HandlerThread handlerThread = new

    HandlerThread(

    "backgroundThread" );

    handlerThread.start();

    MyHandler myHandler = new

    MyHandler(handlerThread.getLooper());

    Message msg = myHandler.obtainMessage();

    //....此处对msg进行赋值,可以创建一个Bundle进行承载

    msg.sendToTarget();

    之后如果需要调用线程,只要对handler传入msg,就可以执行相应的过程了

    最后,很重要的一点,HandlerThread 不随Activity的生命周期结束而消亡,所以必须复写Ondestory(),调用HandlerThread .stop()

    3、使用线程同步 synchronized、 wait()、

    notify()

    使用线程同步机制synchronized实现多线程操作,相对来说比较复杂,但也是灵活性最佳、效率最高的一种做法,在产品开发当中也使用得最广。本人水平相当有限,也只学得一点皮毛。

    synchronized相当于一把锁,当线程运行的时候,会同时有几个线程访问一个对象,对其进行操作或者修改。这可能引起很不良的后果(例如改变判定条件,或者在别的线程还没使用完的时候对象已经被析构等等),所以必须对一些对象进行加锁,保证它在同一时间只允许被一个线程访问。

    synchronized使用方法有两种:

    <1> 同步方法

    在方法名前加入synchronized关键字,则该方法在同一时间内只允许一个线程访问它,其代码逻辑较为简单,但使用起来不太灵活,并且大大降低效率,耗时太长的同步方法甚至会使得多线程失去原本的意义成为单线程

    <2>同步参数 对某一个代码块加锁,并且以synchronized(obj)的方式,表明该代码块内的obj对象是线程同步的。这个做法使得代码灵活性大大加强,缩小同步代码块的范围,并且可以在不同的函数体和类内进行同步,唯一遗憾的是实现起来比较复杂,容易产生一些问题

    而wait()和notify(),必须在synchronized锁的代码块内执行,否则系统将会报错。

    有了以上基础,就可以很容易的创建后台线程了

    Private Runnable backgroundRunnable = new

    Runnable () {

    @Override

    public

    void

    run() {

    if(isFinish){

    //.....

    break;

    }

    for(;;){

    synchronized(this){

    //....写耗时过程

    wait();

    }

    }

    }

    }

    UI线程中,就是一般的创建线程过程了

    Thread backgroundThread = new

    Thread (backgroundRunnable);

    backgroundThread.start();

    这样,在后台线程中会不断的循环,当执行完一次过程以后就会wait()休眠。然后在OnTouchListener或者OnClickListener内相应的位置执行

    synchronized(backgroundRunnable){

    backgroundRunnable.notify();

    }

    当用户触摸屏幕产生一个event的时候,线程就会被唤醒,执行下一次循环。

    最后,还是内存安全问题,必须复写Activity中的OnDestory()方法,将标志量isFinish设为false,并且backgroundThread

    .stop()

    author:zyn

    email:26860002@qq.com

    展开全文
  • java.lang.IllegalThreadStateException at java.lang.Thread.start(Thread.java:595) at thread.ThreadTest.main(ThreadTest2.java:19) 原因是: 1)同一个Thread不能重复调用start方法,跟线程的4状态有关;...

    一、匿名类实现Runnable接口的方式

    public void onClick(View view) {
            switch (view.getId()){
                case R.id.test1:
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("MainActivity----","使用匿名类方式实现线程");
                        }
                    }).start();
                    break;
                case R.id.test2:
    //                myThread mt = new myThread();
    //                mt.start();
                    new myThread().start();
                    break;
                case R.id.test3:
    //                myThread2 mt2 = new myThread2();
    //                Thread t1 = new Thread(mt2);
    //                t1.start();
                    new Thread(new myThread2()).start();
                    break;
            }
        }
    

    二、继承Thread类方式

    class myThread extends Thread{
        @Override
        public void run() {
            super.run();
            Log.i("MainActivity----","使用继承Thread的方式实现线程");
        }
    }
    

    三、实现Runnable接口

    class myThread2 implements Runnable{
    
        @Override
        public void run() {
            Log.i("MainActivity----","通过实现类的方式实现线程");
        }
    }
    

    注:
    如果是重复连续调用start(),如:
    thread1.start();
    thread1.start();
    会出现以下错误:
    Exception in thread “Main Thread” java.lang.IllegalThreadStateException
    at java.lang.Thread.start(Thread.java:595)
    at thread.ThreadTest.main(ThreadTest2.java:19)

    原因是:

    1)同一个Thread不能重复调用start方法,跟线程的4种状态有关;
    2)线程的4种状态:新生状态;可运行状态;阻塞状态;死亡状态
    a. 新生状态:在调用start()方法之前
    b.可运行状态:调用start()方法后,系统为该线程分配除cpu外的所需资源,对于只有一个cpu的机器而言,任何时刻只能有一个处于可运行的线程占用处理机,获得cpu资源,此时系统正正运行线程的run()方法
    c. 阻塞状态:一个正在运行的线程因某种原因不能继续运行时,进入阻塞状态。这是【不可运行】的状态,处于这种状态的线程在得到一个特定的事件后会转回可运行状态
    d. 死亡状态:一个线程的run()运行完毕,stop()方法被调用或者在运行过程中出现了未捕获的异常时,线程进入死亡状态。
    3. 线程的4中状态除了【可运行状态】与【阻塞状态】可以来回切换,其余的不可逆转
    

    同一个Thread不能重复调用start方法,用new Thread(robot).start 就可以启动多次。

    展开全文
  • 首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程创建的,因而Handler和Thread就是相互绑定的,一一对应。而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。HandlerT...

    在多线程编程这块,我们经常要使用Handler(处理),Thread(线程)和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?

    首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程里创建的,因而Handler和Thread就是相互绑定的,一一对应。

    而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。

    HandlerThread顾名思义就是可以处理消息循环的线程,他是一个拥有Looper的线程,可以处理消息循环。

    与其说Handler和一个线程绑定,不如说Handler是和Looper一一对应的。

    Handler是沟通Activity 与Thread/runnable的桥梁。而Handler是运行在主UI线程中的,它与子线程可以通过Message对象来传递数据

    1、首先第一种启用方法是通过继承Thread类,并改写run方法来实现一个线程

    public class MyThread extends Thread {

    //继承Thread类,并改写其run方法

    private final static String TAG = "My Thread ===> ";

    public void run(){

    Log.d(TAG, "run");

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

    {

    Log.e(TAG, Thread.currentThread().getName() + "i = " + i);

    }

    }

    }

    启动

    new Thread(new MyRunnable()).start();

    2、第二种启用方式创建一个Runnable对象

    public class MyRunnable implements Runnable{

    private final static String TAG = "My Runnable ===> ";

    @Override

    public void run() {

    // TODO Auto-generated method stub

    Log.d(TAG, "run");

    for(int i = 0; i<1000; i++)

    {

    Log.e(TAG, Thread.currentThread().getName() + "i = " + i);

    }

    }

    }

    启动

    new Thread(new MyRunnable()).start();

    另外一种启用方式

    btn.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    new Thread(new Runnable() {

    @Override

    public void run() {

    try {

    ...

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }).start();

    }

    });

    3、第三种启用方式通过Handler启动线程

    public class MainActivity extends Activity {

    private final static String TAG = "UOfly Android Thread ==>";

    private int count = 0;

    private Handler mHandler = new Handler();

    private Runnable mRunnable = new Runnable() {

    public void run() {

    Log.e(TAG, Thread.currentThread().getName() + " " + count);

    count++;

    setTitle("" + count);

    // 每3秒执行一次

    mHandler.postDelayed(mRunnable, 3000); //给自己发送消息,自运行

    }

    };

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // 通过Handler启动线程

    mHandler.post(mRunnable); //发送消息,启动线程运行

    }

    @Override

    protected void onDestroy() {

    //将线程销毁掉

    mHandler.removeCallbacks(mRunnable);

    super.onDestroy();

    }

    }

    以上这篇Android 中三种启用线程的方法总结就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

    展开全文
  • 1.新建一个类继承自Thread,并重写run()方法,并在里面编写耗时逻辑。 class ThreadTest extends Thread { @Override public void run() { //具体的耗时逻辑代码 } } new ThreadTest().start();//启动线程 ...

    1.新建一个类继承自Thread,并重写run()方法,并在里面编写耗时逻辑。

    	class ThreadTest extends Thread {
            @Override
            public void run() {
                //具体的耗时逻辑代码
            }
        }
        new ThreadTest().start();//启动线程
    
    

    2.实现Runnable接口。

    	class ThreadTest implements Runnable {
            @Override
            public void run() {
                //具体耗时逻辑
            }
        }
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest).start();//启动线程
    
    

    3.使用匿名内部类。

         new Thread(new Runnable() {
                @Override
                public void run() {
    				//耗时逻辑
                }
            }).start();//启动线程
    
    

    总结:使用继承的方式耦合性有点高,更多的时候选择实现Runnable接口来创建一个线程,但是使用匿名内部类的写法更为常见。

    展开全文
  • 首先说明Android的CPU分配的最小单元是线程,Handler一般是在某个线程创建的,因而Handler和Thread就是相互绑定的,一一对应。而Runnable是一个接口,Thread是Runnable的子类。所以说,他俩都算一个进程。HandlerT...
  • 2.Thread:所有与Handler相关的功能都是与Thread密不可分的,Handler会与创建时所在的线程绑定;3.Message:消息;4.MessageQueue:消息队列,对消息进行管理,实现了一个Message链表;5.Looper:消息循环,从MessageQueue中...
  • 基于Android 6.0源码剖析,分析Android线程创建过程/android/libcore/libart/src/main/java/java/lang/Thread.java/art/runtime/native/java_lang_Thread.cc/art/runtime/native/java_lang_Object.cc/art/runtime/...
  • 看看服务。如果您在应用程序中使用服务,则很多情况下不必进行明确编码。编辑在回应评论,这里就是我如何使用广播接收器public class SomeActivity extends Activity {BroadcastReceiver receiver = new ...
  • /android/libcore/libart/src/main/java/java/lang/Thread.java/art/runtime/native/java_lang_Thread.cc/art/runtime/native/java_lang_Object.cc/art/runtime/thread.cc/system/core/libutils/Threads.cpp/system/...
  • Android关于线程更新UI的方法在一个Android 程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两,除此之外...
  • Android线程创建过程

    2021-06-03 07:54:43
    基于Android 6.0源码剖析,分析Android线程创建过程/android/libcore/libart/src/main/java/java/lang/Thread.java/art/runtime/native/java_lang_Thread.cc/art/runtime/native/java_lang_Object.cc/art/runtime/...
  • 大致流程:创建线程;将主线程上控件的某一属性值创建全局变量;子线程更新全局变量的值;子线程更新完全局变量的值以后通过Handler方式告诉主线程更新控件属性;更新控件属性。 1.安卓创建线程: new Thread()...
  • 前言:看了这么多线程方面的文章,都是比较松散、碎片的知识点,从来没有看到系统的讲解线程以及并发的文章,自从看了微信公众号"code小生"发的一片关于线程方面基础的讲解,文章写的很好,通俗易懂,但是我感觉到很...
  • 如果你要反复执行一个任务,用不同的数据集(参数不同),但一次只要一个执行(任务是单线程的),IntentService符合你的需求。当需要在资源可用时自动执行任务,或允许多任务同时执行,你需要一个线程管理器管理你的...
  • 广州疯狂软件学院拥有大课程体系包括:...Java创建线程三种方法Callable,Runnable,Thread比较及用法编写多线程程序是为了实现多任务的并发执行,从而能够更好地与用户交互。一般有三种方法,Thread,Runnable,Cal...
  • Android线程

    2021-06-08 08:33:41
    Android中实现多线程,常见的方法有:继承Thread类实现Runnable接口ThreadPoolExecutorAsyncTaskHandlerThreadLocalHandlerThreadIntentServiceThread具体使用// 步骤1:创建线程类 (继承自Thread类)class MyThread ...
  • 当我们启动一个App的时刻,Android体系会启动一个Linux Process,该Process包含一个Thread,称为UI Thread或Main Thread。平日一个应用的所有组件都运行在章一?Process中,当然,你可以经由过程修改四大年夜组件在...
  • AndroidStudio 线程

    2021-06-04 12:01:06
    AndroidStudio 线程2019年12月06日阅读数:13这篇文章主要向大家介绍AndroidStudio 线程,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。package com.example.sofia.testactivityactive;...
  • Android线程间通信机制

    2021-02-27 08:58:57
    怎么能保证它只有一个对象,就通过ThreadLocal来保存 创建Handler的两方式## Handler的创建方式有两:一个是在主线程中创建,一个是在普通工作线程创建,两种创建方法是不一样的。Handler在哪个线程创建...
  • android开发中,一说起线程的使用,很多人马上想到new Thread(){...}.start()这种方式。这样使用当然可以,但是多次使用这种方式,会创建多个匿名线程。使得程序运行起来越来越慢。因此,可以考虑使用一个Handler...
  • 在多线程编程这块,我们经常要使用Handler,Thread和Runnable这个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下。2.首先在开发Android应用时必须遵守单线程模型的原则:Android UI操作并不是线程安全的...
  • 但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的。下面总结4中方法用来在线程中操作UI界面。 模拟耗时操作 private void connectNet...
  • Looper.prepare(),主线程使用handler,系统默认prepare了,子线程中创建handler必须在前面Looper.prepare(),后面加上Looper.loop();源码中:主线程:在程序启动的时候,系统已经帮我们自动调用了Looper.prepare()...
  • Android创建线程进行网络访问

    千次阅读 2021-11-25 17:14:14
    下面是子线程代码: 开启子线程服务:new Thread(runnable).start(); 子线程执行的任务: Runnable runnabletday = new Runnable(){ @Override public void run() { try { //String url=ResourceMethod....
  • 什么是线程线程,有时被称为轻量级进程,是程序执行流的最小单元。一个标准的线程线程ID,当前...一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。每一个程序都至少有一个线程,若程序...
  • Android进程间和线程间通信方式

    千次阅读 2021-01-17 13:22:41
    线程自己基本上不拥有系统资源,只拥有一些在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。区别:(1)、一个程序至少有一个进程,一个进...
  • 我有一个工作线程坐在后台,处理消息。这样的东西:class Worker extends Thread {public volatile Handler handler; // actually private, of coursepublic void run() {Looper.prepare();mHandler = new Handler()...
  • 版权声明:本文为博主原创文章,未经博主允许不得转载源码:github.com/AnliaLee大家要是看到有错误的地方或者有啥好的...因此我们需要一通信机制使得子线程完成任务后可以通知UI线程更新界面。本章将挑选线程通...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 194,473
精华内容 77,789
关键字:

android创建线程的三种方法