Android《多线程-上》

什么是线程?

线程本质来说就是一串代码,我们将它交给操作系统来执行。
通常来说我们的CPU任何时候一个核只能处理一个线程,但是目前手机都已经是多核了,顾名思义就是可以同时处理多个线程,也就是能同时处理多件事情。
什么是线程?
这里有人或许会说我们老师说过一个CPU也可以处理多个线程任务,的确大学时老师说过这个,但是我这里是有区别的,在这里会涉及到多核处理与单核多任务处理。

多核处理与单核多任务处理
  • 单核多任务处理原理图
image.png

图解:单核CPU可已处理多个线程任务,但是首先要通过时间片的划分,比如 任务A执行到a1 ,便停止执行任务A开始执行任务B的b1。所以这里实际上CPU 在同一时间永远只执行一个线程,由于电脑的处理速度够快所以给我们感觉是三个线程都在同时执行,千万别被迷惑了。

  • 多核处理
image.png

这个相信完全了可以理解了,同一时间CPU A 和CPU B 都在处理着线程。

线程:线程本质来说就是一串代码,我们将它交给操作系统来执行。
进程:进程是一个“执行中的程序”。

什么是多线程?

多线程:指的是这个程序(一个进程)运行时产生了不止一个线程

用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对,因为反应“多角色”的程序代码,最起码每个角色要给他一个线程吧,否则连实际场景都无法模拟,当然也没法说能用单线程来实现:比如最常见的“生产者,消费者模型”。

这里我引用知乎上的说法:
1.单进程单线程:一个人在一个桌子上吃菜。
2.单进程多线程:多个人在同一个桌子上一起吃菜。
3.多进程单线程:多个人每个人在自己的桌子上吃菜。

好了以上都是让我们加深印象,更容易理解下面的东东。

多线程的实现——Thread和Runnable

对于Android的多线程来说,我们最早学习到的都是Thread和Runnable,通常我们用下面代码启动一个新的线程:

private void startNewThread() {
        new Thread() {
            @Override
            public void run() {
                super.run();
            }
        }.start();
    }
或者
private void startNewThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {

            }
        }).start();
    }

这似乎没什么区别,可是这两个的确是有去别的。
首先Thread 也是一个Runnable,它实现了Runnable接口,在Thread类中有一个 Runnable类型的target字段代表了要被执行的子线程中的任务。

public class Thread implements Runnable {
    ....
    /* What will be run. */
    private Runnable target;

    /* The group of this thread */
    private ThreadGroup group;
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
}

由此可知,实际上最终被线程执行的任务是 Runnable ,而非Thread。Thread只是对Runnable的包装。
这里有个比较有意思的实例我们来研究下:

售票问题,假设现在有三个窗口进行售票(并发执行)。

首先试试Thread

public class MyClass {
    public static void main(String[] args) {
        MyThread1 mt1=new MyThread1("窗口1");
        MyThread1 mt2=new MyThread1("窗口2");
        MyThread1 mt3=new MyThread1("窗口3");
        mt1.start();
        mt2.start();
        mt3.start();
    }
}

class MyThread1 extends Thread{
    private int ticket=10;
    private String name;
    MyThread1(String name)
    {
        this.name=name;
    }

    @Override
    public void run()
    {
        for(int i=0;i<20;i++)
        {
            if(this.ticket>0) {
                System.out.println(name+ "卖票:ticket " + this.ticket--);
            }
        }
    }
}

------------------------------------------------------------------------------------
窗口2卖票:ticket 10
窗口1卖票:ticket 10
窗口1卖票:ticket 9
窗口1卖票:ticket 8
窗口1卖票:ticket 7
窗口1卖票:ticket 6
窗口1卖票:ticket 5
窗口1卖票:ticket 4
窗口1卖票:ticket 3
窗口1卖票:ticket 2
窗口1卖票:ticket 1
窗口3卖票:ticket 10
窗口3卖票:ticket 9
窗口3卖票:ticket 8
窗口2卖票:ticket 9
窗口3卖票:ticket 7
窗口2卖票:ticket 8
窗口3卖票:ticket 6
窗口2卖票:ticket 7
窗口3卖票:ticket 5
窗口2卖票:ticket 6
窗口3卖票:ticket 4
窗口2卖票:ticket 5
窗口3卖票:ticket 3
窗口3卖票:ticket 2
窗口3卖票:ticket 1
窗口2卖票:ticket 4
窗口2卖票:ticket 3
窗口2卖票:ticket 2
窗口2卖票:ticket 1
------------------------------------------------------------------------------------

再看看用Runnable


public class MyClass {
    public static void main(String[] args) {
        MyThread1 mt=new MyThread1();
        Thread t1=new Thread(mt,"窗口1");
        t1.start();
        Thread t2=new Thread(mt,"窗口2");
        t2.start();
        Thread t3=new Thread(mt,"窗口3");
        t3.start();
    }
}

class MyThread1 implements Runnable{
    private int ticket=10;
    @Override
    public void run()
    {
        for(int i=0;i<20;i++)
        {
            if(this.ticket>0) {
                System.out.println(Thread.currentThread().getName()+ "卖票:ticket " + this.ticket--);
            }
        }
    }
}
------------------------------------------------------------------------------------
窗口1卖票:ticket 10
窗口2卖票:ticket 9
窗口1卖票:ticket 8
窗口3卖票:ticket 7
窗口1卖票:ticket 5
窗口2卖票:ticket 6
窗口1卖票:ticket 3
窗口3卖票:ticket 4
窗口1卖票:ticket 1
窗口2卖票:ticket 2
------------------------------------------------------------------------------------
Runnable和Thread区别

实际开发中我们通常采用Runnable接口来实现多线程。因为实现Runnable接口比继承Thread类有如下好处:

  1. 避免继承的局限,一个类可以继承多个接口,但是类只能继承一个类。
  2. Runnable接口实现的线程便于资源共享。而通过Thread类实现,各自线程的资源是独立的,不方便共享。
线程的wait、sleep、join、和yield

对于Thread来说使用比较简单,并没有什么成本,但是通常来说,我们使用的线程基本上都是复写Run函数,然后调用start()函数来启动线程。这些通常在面试时会偶尔的提到,但是线程的wait、sleep、join、和yield可是面试题目中最常提到的。

函数名 作用
wait() 当wait()方法执行时,它就进入到一个和该对象相关的等待池中同时释放了机锁使得其它的县城可以访问,用户可以Notify、notifyAll或者指定时间来唤醒该线程
sleep 该函数是Thread的静态函数,作用是使线程进入睡眠状态,但是对象的机锁并没有释放,其他线程无法访问这个对象。
join 等待目标线程执行完成之后再继续执行
yield 线程礼让,调用线程由运行状态

下一篇我们就直接进入主题进行讲解,这里只是为了理解概念。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容

  • 前言 多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域,所以学好多线程并发编程对我们来说极其重要...
    嘟爷MD阅读 7,303评论 21 272
  • Java 多线程 线程和进程的区别 线程和进程的本质:由CPU进行调度的并发式执行任务,多个任务被快速轮换执行,使...
    安安zoe阅读 2,189评论 1 18
  • 一、进程和线程 进程 进程就是一个执行中的程序实例,每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程。...
    阿敏其人阅读 2,606评论 0 13
  • 作者:魏城 一 历史的河涨潮了 往事倒灌 淹没了记忆的两岸 二 童心是透明的 当你渐渐地长大 世俗开始给你的心 涂...
    魏城阅读 229评论 0 2
  • 我知道你是有梦想的,你不甘平庸,你不安现状,你对未来有美好的憧憬,你想要更好的生活,成为更好的自己。 你羡慕那个已...
    淮左云澜阅读 554评论 0 4