zoukankan      html  css  js  c++  java
  • Android多线程研究(1)——线程基础及源代码剖析

    从今天起我们来看一下Android中的多线程的知识,Android入门easy,可是要完毕一个完好的产品却不easy,让我们从线程開始一步步深入Android内部。

    一、线程基础回想

    package com.maso.test;
    
    public class TraditionalThread {
    
    	public static void main(String[] args) {
    		/*
    		 * 线程的第一种创建方式
    		 */
    		Thread thread1 = new Thread(){
    			@Override
    			public void run() {
    				try {
    					sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while(true){
    					System.out.println(Thread.currentThread().getName());
    				}
    			}
    		};
    		thread1.start();
    		
    		/*
    		 *线程的另外一种创建方式 
    		 */
    		Thread thread2 = new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while (true) {
    					System.out.println(Thread.currentThread().getName());
    				}
    			}
    		});
    		thread2.start();
    		
    		/*
    		 * 线程的调用优先级
    		 */
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while(true){
    					System.out.println("Runnable");
    				}
    			}
    		}){
    			public void run() {
    				try {
    					sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while(true){
    					System.out.println("Thread");
    				}
    			};
    		}.start();
    	}
    }
    
    上面代码中是我们都非常熟悉的线程的两种创建方式,假设对这些还感到陌生请先看Java线程基础。


    打开Thread类的源代码能够看到Thread类有8个构造函数。我们先看看上面的两种构造函数的源代码。

        public Thread() {
            init(null, null, "Thread-" + nextThreadNum(), 0);
        }
    在构造的时候直接调用了init方法

        private void init(ThreadGroup g, Runnable target, String name,
                          long stackSize) {
            if (name == null) {
                throw new NullPointerException("name cannot be null");
            }
    
            Thread parent = currentThread();
            SecurityManager security = System.getSecurityManager();
            if (g == null) {
                /* Determine if it's an applet or not */
    
                /* If there is a security manager, ask the security manager
                   what to do. */
                if (security != null) {
                    g = security.getThreadGroup();
                }
    
                /* If the security doesn't have a strong opinion of the matter
                   use the parent thread group. */
                if (g == null) {
                    g = parent.getThreadGroup();
                }
            }
    
            /* checkAccess regardless of whether or not threadgroup is
               explicitly passed in. */
            g.checkAccess();
    
            /*
             * Do we have the required permissions?

    */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }

    里面的东西比較多。可是我们能够看到会初始化一个变量Runnable  target;

    以下我们再来看看run方法中是个什么东东?

        @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    原来run方法中会先推断是否初始化了Runnable target变量,假设没有则空实现,假设target不为空则先运行Runnable接口中的run方法。

    有的朋友可能会猜想以下的代码会先调用Runnable接口中的run方法,然后才调用Thread实现类中的run方法。

    		/*
    		 * 线程的调用优先级
    		 */
    		new Thread(new Runnable() {
    			
    			@Override
    			public void run() {
    				try {
    					Thread.sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while(true){
    					System.out.println("Runnable");
    				}
    			}
    		}){
    			public void run() {
    				try {
    					sleep(1000);
    				} catch (InterruptedException e) {
    					e.printStackTrace();
    				}
    				while(true){
    					System.out.println("Thread");
    				}
    			};
    		}.start();
    事实上事实并不是如此。由于上面代码中是一个匿名内部类,实际上是一种从Thread的继承和实现,所以以下的run方法覆盖了Thread中的run方法。所以Runnable中的run方法根本不会运行。

    以下再看看Runnable接口的源代码

    public
    interface Runnable {
        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see     java.lang.Thread#run()
         */
        public abstract void run();
    }
    
    发现Runnable接口仅仅有一个抽象的run方法。

    为什么要搞一个Runnable接口来实现多线程呢?从Thread继承不是更方便吗?Runnable接口有例如以下优势。所以我们经常会选择实现Runnable接口:

    1、适合多个程序代码的线程去处理同一个资源。

    public class ThreadTest1 extends Thread {
    	private int count = 5;
    	 
        public void run() {
            for (int i = 0; i < 7; i++) {
                if (count > 0) {
                    System.out.println("count= " + count--);
                }
            }
        }
     
        public static void main(String[] args) {
        	//这样实际上是创建了三个互不影响的线程实例
            ThreadTest1 t1 = new ThreadTest1();
            ThreadTest1 t2 = new ThreadTest1();
            ThreadTest1 t3 = new ThreadTest1();
            t1.start();
            t2.start();
            t3.start();
        }
    }
    public class ThreadTest1{
         
        public static void main(String [] args) {
            MyThread my = new MyThread();
            //开启了三个线程。可是操作的是同一个run方法
            new Thread(my, "1号窗体").start();
            new Thread(my, "2号窗体").start();
            new Thread(my, "3号窗体").start();
        } 
    }
    
    class MyThread implements Runnable{
    	 
        private int ticket = 5;  //5张票
     
        public void run() {
            for (int i=0; i<=20; i++) {
                if (this.ticket > 0) {
                    System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
                }
            }
        }
    }

    2、避免Java特性中的单根继承的限制。

    3、能够保持代码和数据的分离(创建线程数和数据无关)。

    4、更能体现Java面向对象的设计特点。




  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    微信小程序TodoList
    C语言88案例-找出数列中的最大值和最小值
    C语言88案例-使用指针的指针输出字符串
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6862413.html
Copyright © 2011-2022 走看看