Android 中的线程应用_项海涛

Android 中的线程应用

1.Android 线程应用基础(Thread,Runnable)
2.Android 中的消息模型(Message,MessageQueue,Handler,Looper)
3.Android 中的异步任务(AsyncTask)
4.Android 中线程池的应用(Executor,ExecutorService

一.Android 线程应用基础
1.何为线程(Thread)?

线程是进程中的一个顺序的执行流,在Java中表现形式为Thread类型的对象。
进程:正在运行的一个程序,有自己独立的内存空间,可以启动多个线程并发执行。在一个多任务操作系统中允许多个进程并发执行。
说明:真正的并发是要构建于过个处理器的基础之上的。

2.多线程的优势,劣势?

1)优势:可以提高系统的并发处理能力,改善用户体验。 
2)劣势:可能会导致线程安全问题。

3.Java 中线程对象的创建及应用?

Java 中线程的类型为Thread类型,我们可以通过此类型构建线程对象,并调用对象的start方法启动线程,线程启动以后会执行Thread类的run方法,我们可以将自己要执行的任务写在run方法中。

构建线程对象时,常用的构造方法: 
    1)Thread(); 
    2)Thread(Runnable r);

4.线程状态及相关方法应用?

 线程状态:

1.新建状态: new Thread() 
2.就绪状态: start() 
3.运行状态: run() 
4.阻塞状态: sleep(3000),i/o阻塞 
5.死亡状态: run()方法执行结束

 线程方法:
 1)start
 3)sleep
 4)setName (设置线程名字)
 5)setPriority (设置优先级)
 6)currentThread():获得当前线程   
 7)getName()....
 8)setDaemon(true) 设置线程为守护线程
 9)............

5.线程的同步?(重点,难点)
线程同步指多个线程在共享数据集上的互斥,协作(通讯)。同步的目的是为了保证数据的安全,让数据更符合我们的业务要求。

互斥的实现方式:

1)同步代码块synchronized(对象锁){被锁的内容}
2)同步方法(静态,非静态)

synchronized static void method(){} 对象锁为类对象 
synchronized void method(){} 对象锁为this

说明:
1)加锁以后会影响系统的执行效率
2)在保证数据安全的情况下,锁的范围越小越好。

协作的实现方式:(保证业务的合理性)协作是构建在互斥的基础之上,然后借助Object对象的wait,notifiy,notifyall方法实现线程之间的通讯。

1)wait:等待(阻塞当前线程,并释放对象锁)
2)notifiy/notifyall:通知具备相同锁的对象开始执行。

说明:
1)wait,notifiy,notifyall必须用于同步代码块或同步方法内部
2)wait,notifiy,notifyall需要由对象锁调用。

demo 普通线程的创建及使用

//普通线程创建及使用(不考虑线程同步)
/**运行在主线程*/    
public static void main(String[] args) { 
       //在主线程创建工作线程   
       thread th=    new Thread(){
       //工作线程           
       public void run() {                
          method01();         
          };     
};    
 //t.setDaemon(true);
 //设置线程为守护线程(如果需要设置守护线程 需要设置在线程启动之前)       
  th.start();//启动线程(处于就绪状态)    
      new Thread(new Runnable() {//target            
      @Override          
      public void run() {          
           method02();//此方法要运行在另一个工作线程         
       }       
 }).start(); //thread.run-->target.run   
      //在主线程执行method03     
        method03();
 } 

线程的同步之互斥
例子:多线程下的单例模式

class Singleton01{  
  private Singleton01(){} 
  private static Singleton01 instance;
  //同步锁(锁可以是唯一的任意对象)    
  final static String LOCK="LOCK";//第一种写法 同步代码块    
  public static Singleton01 getInstance() {         
     synchronized (Singleton01.class) {     
     //同步代码块              
     if(instance==null){             
          instance=new Singleton01();            
      }           
       return instance;        
   }
   //线程在执行此代码块时会获得锁,执行完以后释放锁。    
}    
/**第二种写法:同步方法     
 * 1)静态方法默认使用类对象作为对象锁     
 * 2)非静态方法默认使用this作为对象锁     
 * */   
 public synchronized static Singleton01 getInstance() {        
     if(instance==null){            
         instance=new Singleton01();        
       }        
         return instance;    
      }    
      //第三种写法:双重验证同步 (更高效)    
      public static Singleton01 getInstance() {        
      if(instance==null){        
          synchronized (Singleton01.class) {
          //同步代码块            
          if(instance==null){                
              instance=new Singleton01();            
         }        
          }        
       }       
       return instance;       
       //线程在执行此代码块时会获得锁,执行完以后释放锁。    
       }
}
       public class ThreadDemo03 {    
       static class Task implements Runnable{        
       @Override        
       public void run() {        
       System.out.println(           
           Singleton01.getInstance());        
       }    
   }    
   public static void main(String[] args) {        
           Task task=new Task(); 
           new Thread(task).start();
           new Thread(task).start();
           new Thread(task).start();
           new Thread(task).start();
   }

**线程同步之线程协作
生产者与消费者模型DEMO**

/** 容器对象 */
class Container {
    public Object[] datas;
    /** 通过此变量记录有效元素个数 */
    private int size;

    public Container(int cap) {
        this.datas = new Object[cap];
    }

    /** 此方法用于向容器放数据:要求满了则等待 */

    public synchronized void put(Object data) {
        // this
        // 1.判定容器是否已满,满了则等待
        if (datas.length == size)
            try {
                this.wait();
            } catch (Exception e) {
            }
        // throw new RuntimeException("容器已满!");
        // 2.容器不满则继续放数据
        datas[size++] = data;
        // 3.通知消费者(具备相同锁)可以取数据
        this.notifyAll();
    }

    /** 此方法用于从容器取数据:要求空了则等待 */
    public synchronized Object take() {
        // this为对象锁
        // 1.判定容器是否为空,空则等待
        if (size == 0)
            try {
                this.wait();
            } catch (Exception e) {
            }
        // throw new RuntimeException("容器没有数据!");
        // 2.取数据
        Object temp = datas[0];
        // 3.数组往前移(数组长度减1)
        System.arraycopy(datas, 1, datas, 0, size - 1);
        size--;
        datas[size] = null;
        // 3.通知生产者(具备相同锁对象)可以继续放数据
        this.notifyAll();
        return temp;
    }
}

/** 生产者对象:向容器放数据 */
class Producer extends Thread {
    private Container container;

    public Producer(Container container) {
        this.container = container;
    }

    /** 生产者可以不断的放数据 */
    @Override
    public void run() {
        int num = 0;
        while (true) {
            num++;
            System.out.println("producer.put=" + num);
            container.put(num);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
        }
    }
}

/** 消费者对象:从容器取数据 */
class Consumer extends Thread {
    private Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        while (true) {
            Object data = container.take();
            System.out.println("consumer.take=" + data);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
            }
        }
    }
}

public class ThreadCommuniation01 {
    public static void main(String[] args) { 
        // 构建容器对象 Container c=new

        // Container(5);

        //BlockingQueue<Object> q=new

        // ArrayBlockingQueue<>(5);

        //构建生产者对象 Producer pro=new

        // Producer(c); //构建消费者对象

        // Consumer con=new Consumer(c);

        // //启动线程 pro.start();

        // con.start(); }}
    }

二.Android 中的消息模型(Message,MessageQueue,Handler,Looper)
为什么要使用消息模型
使用Android中消息模型的目的是尽量不要去阻塞主线程,然后给用户一种比较友好的体验。

1.Android 中消息模型关注对象:

Message :数据的载体
MessageQueue: 存储多个消息对象
Looper:迭代消息队列,取出消息。
Handler:发送,处理消息队列中的消息。

2.Android 中消息模型应用案例?

1.工作线程发消息给主线程? 
2.主线程发消息给主线程? 
3.主线程发消息给工作线程?

3.记住:

1)主线程在启动时已经默认创建了Looper和消息队列对象 
2)给谁发消息就让handler关联谁的Looper. 
3)handler的handleMessage方法运行在哪个线程由handler关联的looper而定。

4.Android 中消息模型对象相关方法总结

1)Message(obj,what,obtain(),….) 
2)MessageQueue 
3)Looper(prepare(),myLooper(),loop(),getMainLooper(),quit()) 
4)Handler(sendMessage,handleMessage,sendXXXXX) 

demo
工作线程发消息给主线程

public class MainActivity extends Activity {
    private Handler mHandler;

    /** onCreate方法运行在主线程 */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 构建一个Handler,关联主线程的Looper
        // 主线程在启动时会创建一个Looper,并关联一个消息对象
        // 默认关联当前线程looper
        // 主线程创建时默认创建一个looper,不需要再次创建(除了主线程都需要创建looper)
        // mHandler=new Handler(){
        mHandler = new Handler(Looper.getMainLooper()) {
            // 当handler关联的looper所在线程收到消息以后会回调此方法
            // 在此方法中可以执行消息的处理操作
            // 此方法运行在哪个线程取决于handler关联的looper
            // 一个线程最多有一个Looper对象
            public void handleMessage(Message msg) {
                if (msg.what == 1) {
                    // what表示做什么
                    isExit = false;
                    return;
                }
                setTitle((String) msg.obj);
            };
        };
    }

    public void onClick01(View v){        
        new Thread(){            
            @Override            
            public void run() {                
                try{sleep(5000);}catch(Exception e){}                
                //要发送的数据                
                String s="helloworld01";                
                //将如上数据交给主线程                
                //1.构建消息对象              
                Message msg=new Message();                                
                //赋值                
                msg.obj=s;                
                //2.将消息对象发送给主线程                
                //记住:消息发送给谁,取决于handler关联的looper                
                mHandler.sendMessage(msg);            
                }        
            }.start();    
            }    
    boolean isExit;    
    /**点击回退操作3秒内重复点击退出 否则无效的方法*/    
    @Override    
    public void onBackPressed() {        
        if(!isExit){        
            Toast.makeText(this, "再点一次则退出",1).show();        
            isExit=true;
            //第一种写法,线程等待3秒        
            /*new Thread(){           
             *  public void run() {                
             *  try{sleep(5000);}catch(Exception e){}                
             *  isExit=false;            
             *  };        
             *  }.start();*/
            //第二种写法,直接在工作线程创建handler延迟发送消息        
            /*new Handler(Looper.getMainLooper()){          
             * public void handleMessage(Message msg) {              
             * isExit=false;          
             * };        
             * }.sendEmptyMessageDelayed(1, 3000);
             * *///向主线程发送带有what参数的延迟消息        
            mHandler.sendEmptyMessageDelayed(1,3000);           
            }else{        
                finish();        
                }    
        }
    }

主线程向工作线程发消息

public class MainActivity extends Activity {    
    @Override    
    protected void onCreate(Bundle savedInstanceState) {        
        super.onCreate(savedInstanceState);        
        setContentView(R.layout.activity_main);    
        }    
    private Looper wLooper;    
    //在此方法中发消息给工作线程    
    public void onClick(View v){       
        //构建工作线程       
        new Thread(){public void run(){           
            //创建一个looper,并绑定到当前线程           
            Looper.prepare();           
            //获得当前线程Looper           
            synchronized (MainActivity.this) {               
                wLooper=Looper.myLooper();               
                MainActivity.this.notify();           
                }           
            //迭代消息队列           
            Looper.loop();       
            }}.start();       
            synchronized (this) {        
                if(wLooper==null)
                    try{
                        this.wait();
                        }catch(Exception e){

                        }       
                }       
            //构建handler对象            
            //此方法运行在工作线程中  此方法运行在哪个线程 取决于绑定了哪个线程的looper (需要解决同步问题)      
            Handler h=new Handler(wLooper){          
                public void handleMessage(Message msg) {              
                    String tname=Thread.currentThread().getName();              
                    Log.i("TAG", tname+"-->"+msg.obj.toString());           
                    };       
                    };       
                    //发送消息       
                    Message msg=Message.obtain();
                    //获得一个消息       
                    msg.obj="hello work thread";       
                    h.sendMessage(msg);    
                    }
    }

主线程给主线程发送消息

public    void onClick(View v){     
    Handler h = new Handler(
            Looper.myLooper()){         
        @Override        
        public void handleMessage(Message msg) {            
            Log.i("TAG",""+msg.obj);        
            }     
        };     
        Message msg =new Message();     
        msg.obj="hello";     
        //第一种 可以在主线程里面执行 sendMessage方法    
        // h.sendMessage(msg);     
        //第二种 执行post方法  post方法在线程执行     
        h.post(new Runnable() {        
            @Override        
            public void run() {            
                Log.i("TAG","run()");        
                }    
            });
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值