Android 多线程:Thread理解和使用总结
Android Thread目录.png 一、Android中的Thread定义:线程,欧博allbet可以看作是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。 1.1 Thread主要函数 函数名 作用run() 线程运行时所执行的代码 start() 启动线程 sleep()/sleep(long millis) 线程休眠,进入阻塞状态,sleep方法不会释放锁(其它线程不会进入synchronized方法体或方法块,不释放锁需要try/catch) yield() 线程交出CPU,但是不会阻塞而是重置为就绪状态,不会释放锁 join()/join(long millis)/join(long millis,int nanoseconds) 线程插队,当该子线程执行完毕后接着执行其它 wait() 进入阻塞状态,释放锁(其它线程可以进入synchronized方法体或方法块,释放锁不需要try/catch) interrupt() 中断线程,注意只能中断阻塞状态的线程 getId() 获取当前线程的id getName()/setName() 获取和设置线程的name getPriority()/setPriority() 获取和设置线程的优先级,范围1-10,默认是5 setDaemon()/isDaemo() 设置和获取是否守护线程 currentThread() 静态函数获取当前线程 1.2 Thread的几种状态 新建状态(new):实例化之后进入该状态; 就绪状态(Runnable):线程调用start()之后就绪状态等待cpu执行,注意这时只是表示可以运行并不代表已经运行; 运行状态(Running):线程获得cpu的执行,开始执行run()方法的代码; 阻塞状态(Blocked):线程由于各种原因进入阻塞状态:join()、sleep()、wait()、等待触发条件、等待由别的线程占用的锁; 死亡状态(Dead):线程运行完毕或异常退出,欧博百家乐可使用isAlive()获取状态。 二、Android中Thread的使用这里写出三种使用方式: 2. 实现Runnable,重写run()方法来执行任务。 public class MyRunnable implements Runnable{ @Override public void run() { // do something } } new Thread(new MyRunnable()).start();另一种启动方式 new Thread(new Runnable() { @Override public void run() { } }).start();3. 通过Handler启动线程。 然后使用mHandler的post()方法执行线程。当上方的Runnable执行后里面定义了mHandler.postDelayed(runnable,1000);开启延迟1000毫秒后再次执行。 findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mHandler.post(runnable); // handler运行runnable } }); 三、Thread使用其它问题 3.1 如何终止线程1. 使用boolean变量作为标记 2. 使用interrupt() (1) 线程正常运行状态 (2) 线程阻塞状态 当我开始和终止该线程后Log如下: 10-14 19:46:57.562 32024-32227/com.sky.androidthreadapp I/thread: Thread-16142:Running()_Count:1 10-14 19:46:58.562 32024-32227/com.sky.androidthreadapp I/thread: Thread-16142:Running()_Count:2 ... 10-14 19:47:01.564 32024-32227/com.sky.androidthreadapp I/thread: Thread-16142:Running()_Count:5 10-14 19:47:01.931 32024-32227/com.sky.androidthreadapp I/thread: Thread-16142异常抛出,停止线程可以看到调用interrupt()方法后抛出InterruptedException异常,同时break跳出循环达到停止跑代码的作用。原理是当线程进入阻塞状态时,调用interrupt()方法会抛出异常,利用这个异常来跳出循环。 3. 使用stop()方法终止线程 1. 什么是线程安全问题 基本上所有的并发模式在解决线程安全问题的问题上,都采用“序列化访问临界资源”的方案,即在同一时刻只能有一个线程访问临界资源(多个线程可能同时访问的数据或资源),也称同步互斥访问。 (1) synchronized 关键字,保证同时刻只有一个线程进入该方法或者代码块,使用方式(Tips:java中有很多方式来实现线程同步,我们常用的synchronized是效率最低的...但是它方便啊): 线程run()方法中要执行的代码方法添加synchronized关键字,注意要添加在方法的返回值前。 int count = 100; private synchronized void count() { if (count > 0) { Log.e(TAG, Thread.currentThread().getName() + "--->" + count--); } else { isRunning = false; } }同步代码块的形式使用。 private void count() { synchronized (this) { if (count > 0) { Log.e(TAG, Thread.currentThread().getName() + "--->" + count--); } else { isRunning = false; } } }(2) 特殊域变量volatile修饰变量:告诉虚拟机该变量随时可能更新,因此使用时每次都会重新计算,而不是使用寄存器的值。volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。(不能完全保证线程安全) private volatile int count = 1000;(3)使用重入锁实现线程同步。 ReentrantLock() : 创建一个ReentrantLock实例 lock() :获得锁 unlock() : 释放锁 private void count() { lock.lock(); if (count > 0) { Log.e(TAG, Thread.currentThread().getName() + "--->" + count--); } else { isRunning = false; } lock.unlock(); }(4)ThreadLocal管理变量。如果一个变量使用ThreadLocal进行管理,每一个使用该变量的线程都会获得该变量的副本,副本之间相互独立,所以每个线程都可以修改变量而不会对其它线程造成影响。 private static ThreadLocal<Integer> number = new ThreadLocal<Integer>(){ // 重写方法,设置默认值 @Override protected Integer initialValue() { return 1; } // 自定义方法设置变量值 public void saveNumber(int newNumber){ number.set(number.get() + newNumber); } // 自定义方法获取变量值 public int getNumber(){ return number.get(); } };相关文章: |