Android_原理篇_线程的控制和原理(简单)

一、说起Android线程就不得不提到java,因为AndoridSDK中并没有开发新的线程,而是沿用了java的线程机制,所以接下来给大家深入讲解java中的线程,不足之处希望批评指正!!吐舌头

二、Java中的线程:

一般来理解java中的线程有两种:1、

继承Thread类
/**
     * 继承Thread方式
     */
    private class TestThread extends Thread {

        TestThread(String name) {
            super(name);
        }

        @Override
        public void run() {
           //执行耗时操作
        }
    }
举个例子:
TestThread testThread1 = new TestThread ("线程一");
 TestThread testThread2 = new TestThread ("线程二");
 TestThread testThread3 = new TestThread ("线程三");

 testThread1.start();
 testThread2.start();
 testThread3.start();
2、
实现Runnable接口
/**
     * 实现Runnable方式
     */
    private class implements Runnable {
        @Override
        public void run() {
            //执行耗时操作
        }
    }
TestRunnable testRunnable = new TestRunnable();
Thread thread1 = new Thread(testRunnable , "线程一");
Thread thread2 = new Thread(testRunnable , "线程二");
Thread thread3 = new Thread(testRunnable , "线程三");

thread1.start();
thread2.start();
thread3.start();

 举例: 
 
说完了实现线程两种方式,插播一段,先来简单说下java线程池,java线程池在
package java.util.concurrent
这个包里面,想必大家也比较清楚



这几个类希望大家一定要了解,不懂得可以网上搜索 java线程池,这里只告诉 大家这几种线程池都有自己用处,像轮询、定时器用ScheduledThread,单一队列SingleThread,并发CachedThread、FixedThread都行,但具体问题具体对待,本文不是对线程池介绍的,所以还望见谅,就到这里。
  这时候有人其实就会问:java已经有封装好的线程池了,拿来用就是了,干嘛还要用传统的Thread呢?
 其实,我这篇文章是介绍线程的原理,万变不离底层,不管是上层再怎么封装,只要知道了原理,其实也就明白了本质。
  三、Thread原理:
好了,言归正传,先来看看Thread里面的方法:

Thread主要函数

run()//包含线程运行时所执行的代码 

start()//用于启动线程

sleep()/sleep(long millis)//线程休眠,交出CPU,让CPU去执行其他的任务,然后线程进入阻塞状态,sleep方法不会释放锁

yield()//使当前线程交出CPU,让CPU去执行其他的任务,但不会是线程进入阻塞状态,而是重置为就绪状态,yield方法不会释放锁

join()/join(long millis)/join(long millis,int nanoseconds)//等待线程终止,直白的说 就是发起该子线程的线程 只有等待该子线程运行结束才能继续往下运行

wait()//交出cpu,让CPU去执行其他的任务,让线程进入阻塞状态,同时也会释放锁

interrupt()//中断线程,自stop函数过时之后,我们通过interrupt方法和isInterrupted()方法来停止正在运行的线程,注意只能中断已经处于阻塞的线程

getId()//获取当前线程的ID

getName()/setName()//获取和设置线程的名字

getPriority()/setPriority()//获取和这是线程的优先级 一般property用1-10的整数表示,默认优先级是5,优先级最高是10,优先级高的线程被执行的机率高

setDaemon()/isDaemo()//设置和判断是否是守护线程

currentThread()//静态函数获取当前线程

Thread线程主要状态

(1) New  一旦被实例化之后就处于new状态

(2) Runnable 调用了start函数之后就处于Runnable状态

(3) Running 线程被cpu执行 调用run函数之后 就处于Running状态

 (4)   Blocked 调用join()、sleep()、wait()使线程处于Blocked状态

 (5)   Dead    线程的run()方法运行完毕或被中断或被异常退出,线程将会到达Dead状态

如何停止一个线程

通过上面的函数列表,我可以知道通过interrupt方法和isInterrupted()方法来停止正在运行的线程,首先必须先让线程处于阻塞状态

/**
     * 销毁线程方法
     */
    private void destroyThread() {
        try {
            if (null != thread && Thread.State.RUNNABLE == thread .getState()) {
                try {
                    Thread.sleep(1000);
                    thread .interrupt();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            thread = null;
        }
    }
可能会抛出InterupterExecption。

实现Runnable接口的多线程例子

/** 
* 实现Runnable接口的类
* 
*/ 
publicclass DoSomethingimplements Runnable {
    private String name;

    public DoSomething(String name) {
        this.name = name;
    } 


    public void run() {
        for (int i = 0; i < 5; i++) {
            for (long k = 0; k < 100000000; k++) ;
            System.out.println(name + ": " + i);
        } 
    } 
}
/** 
* 测试Runnable类实现的多线程程序
*  
*/ 
publicclass TestRunnable {
    publicstaticvoid main(String[] args) {
        DoSomething ds1 = new DoSomething("阿三");
        DoSomething ds2 = new DoSomething("李四");

        Thread t1 = new Thread(ds1);
        Thread t2 = new Thread(ds2);

        t1.start(); 
        t2.start(); 
    } 
}
看看日志:

李四: 0
阿三: 0 
李四: 1 
阿三: 1 
李四: 2 
李四: 3 
阿三: 2 
李四: 4 
阿三: 3 
阿三: 4 
日志告诉我们,多线程并发是没有顺序的,当然通过一些方法,join,yeild是可以调控线程的执行顺序的,但这种东西在Android中的应用场景微乎其微。

况且本来Android的主线程就不允许有耗时操作,所以在Android应用开发过程中线程异步加载才是主流应用场景。

四、举例:

Android比较常见的场景就是异步加载网络图片,当页面上存在图片列表的时候,多线程下载就很重要,如果单线程下载,用户的网络不好,很可能导致很长时间页面没有出图,这样体验是很差的。

假如:现在一页加载5张图,分别来自5个url,我们开启了5个线程并发加载,有两种业务需求:1、异步刷新界面展示。2、当5张图片都下载完成后,返回界面展示。

第一种还好说,只要是图片下载完成一个接口回调刷新就完了。

但如果是第二种呢,怎么判断5张图片都下载完了呢??这里其实也不难,ThreadCount就可以搞定,ThreadCount我认为他就是一个标记(TAG),当你int ThreadCount =5;时候,假设有一个图片记载完成,你就在返回结果ThreadCount--;并判断

if(ThreadCount ==0){

//刷新,展示数据

};

直到所有的图片都应经下载完成,就能执行if里面的代码。

仔细看看Okhttp3

还有响应式Rxjava2


都用到了线程标记。

最后还是那句话,万变不离其宗,希望大家互相学习,掌握学习方法,不断提高!



发布了19 篇原创文章 · 获赞 19 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/baidu_30084597/article/details/79134426