Thread

来源:互联网 发布:高二数学算法初步 编辑:程序博客网 时间:2024/04/29 05:50

进程:每个运行中的程序,每个app。他们拥有自己独立的资源,每个进程都有自己独立的地址空间。没经允许,其他进程不能访问其地址空间。

线程:   每个进程可以有多个线程,线程之间是独立的。


线程创建启动:

一.继承thread,重写线程执行体run()方法

public MyThread extends Thread(){

public void run(){

...

}

}

Thread thread=new MyThread();

thread.start();


二.实现Runnable接口,重写该接口的run()方法。将其作为thread的target传入,线程负责调用target里面的run方法

new Thread(new Runnable(){

public void run(){

...

}

}).start();


三.使用Callable接口配合Future,此种方式不多写了


线程生命周期:

新建(new)   new实例化

就绪(runnable) 调用start了

运行(running)   系统线程调度,得到处理器资源

阻塞(blocked)   sleep   调用阻塞IO方法等等

死亡(dead)


知道上面这些知识以后,我们就可以想一下,那线程的控制问题

首先,介绍几个简单的线程控制方法

join方法    主线程中,开启一个子线程,并调用子线程的join方法。那么主线程会在子线程结束以后才可以继续运行

setDaemon方法   设置为true就是后台线程了   必须在start启动之前设置,当所有前台线程死亡,后台线程会自动死亡

sleep(暂停)和yeid(退让给更高优先级)


线程异步,我们会接触到很多,也不需要我们做很多的控制。所以,下面就说说线程同步的问题

Class A{

private int a=100;

public void operateA(){

if(a>0){

a--;

}

Log.i("test","a="+a);

}

//下面两个方法是判断对象是否是同一个

hashCode(){}

euqals(Object object){}

}

有一个实体类A,提供一个数据a,和一个操作a的方法

现在有多个线程去调用operateA方法对a进行操作,如果我们不加任何控制,多个线程就是并发的去修改数据a。那么,想象一下:

a=1

此时一个线程刚好通过判断进来,还没执行a--。线程调度,正好另一个线程执行,那么最终就会出现a=-1的情况,当然几率很小,但并不代表没有。所以我们应当考虑同步的问题:同步就是多线程并发时,只有一个线程能进入同步的方法或代码块执行数据操作

那么上面的代码怎么改呢,就改个同步的方法吧:

public synchronized void operateA(){

if(a>0){

a--;

}

Log.i("test","a="+a);

}

就是加了个synchronized。其实同步方法本质就是:对象本身是同步监视器,给对象上锁。上了锁,我们就能保证同一个对象,多个线程对这个对象操作时,某一时刻一个线程可以操作该对象的operateA方法。也就是你只new了一个A对象,多个线程对其进行operateA操作,某一时刻只有一个线程在执行operateA。

提到了锁的概念,这篇就不多讲了,下一篇讲。


保证线程可以同步了,那在同步的时候,我们有时候也是需要线程之间互相通信来协调下一步怎么走。那接下来就说说线程间的通信吧

为了篇幅不会太长(其实就是不熟啦,哈哈哈),就不会给代码了   

下面介绍一种通信方式是调用wait()方法,当前线程等待,但释放了对象锁。使得对同一个对象的并发操作的其他线程可以获得对象锁从而调用它的同步的方法。notifyAll(),所有使用wait方法的线程唤醒,等待获取对象锁从而进入运行状态 

有一个实体类People

public Class People{

private int num;

private int money;

//标记money是否大于0

private Boolean flag=false;

//多线程时候,实体类的标配,为什么要写,百度

hasCode(){}

equals(){}

public People(int num,int money){

this.num=num;

this.money=money;

}

//取钱的方法

public synchronized void draw(){

//没钱的时候,调用wait等待

while(!flag){

wait();

}

//有钱了,就进入下面的具体取钱动作

...

//取完钱 flag设置为false

flag=false;

}

//存钱的方法

public synchronized void deposit(){

//有钱的时候,调用wait等待

while(flag){

wait();

}

//没钱了,就进入下面具体的存钱动作

...

/存完钱 flag设置为true

flag=true;

notifyAll();

}

}

有了上面那个实体类以后呢,我们在实现2个线程  一个实现取钱,就是调用people的draw方法

一个实现存钱,就是调用people的deposit方法

activity里面只开启一个取钱的线程,会发现线程会阻塞在while判断里面,可以加点log去验证下

只有再添加一个存钱的线程,我们才能成功取钱

这个例子到底要说什么,就是我们实现同步,就能保证同一个people,某一时刻只有一个线程可以执行people的存钱或者存钱动作。当我们加了wait之后,我们就能实现先存钱然后才能取钱。就相当于实现了线程之间的一个通讯:我完成存钱动作了,你才能取钱。通常这种表现就是线程通讯。

线程通讯除了wait notify,我们还可以使用condition配合锁实现。或者Blockingqueue实现。如果有同学想知道我对这两个的一个认知,我可以献上~

本篇文章提到了对象锁,我会在另一篇中说说。



0 0
原创粉丝点击