您的位置:首页 > 理论基础

文章标题多线程概述和基本使用

2017-10-10 09:51 218 查看
一、概念

进程:一个应用程序启动,就说一个进程启动。进程是计算机进行资源分配的基本单位

线程:程序运行过程中的最小执行单位。一个进程可以包含多个线程。

程序:静态概念。

多线程的目的:最大限度的利用cpu的资源,提高程序运行效率。

二、线程

面向对象的编程:

1.抽象:对象所具有的共有的特征和行为

class Thread{

void run(){

//指明线程所要执行的过程,流程。

}

void start();

}

new Thread().start();

三、线程三要素:

1.cpu : 软件cpu 共享

2.code :

3.Data

四、多线程的机制:

1. java.lang.Thread{

void run(){

//指定当前线程所要完成的任务。

}

void start();用来给cpu发送执行信号,当这个方法执行就代表告诉cpu当前线程准备就绪,可以执行。

}

2.java中多线程的实现方式:

1) extends Thread:

class SubThread extends Thread{

public void run(){

//….

}

}

new SubThread().start();

2) implements Runnable:

class SubRunnable implements Runnable{

public void run(){

//…..

}

}

SubRunnable sr = new SubRnnable();

new Thread(sr).start();

3.两种方式的比较。

java不能多继承

class Father{}

class Son extends Father{}

五、线程状态间的转换:

1.初始状态(新建状态)

刚刚使用new关键字创建出来的线程对象。

2.就绪状态:

新建的线程对象调用start方法之后就进入就绪状态。称之为准备好了的状态(万事俱备只欠东风)。只等cpu调度。

如果对一个已经处于就绪状态的线程再次调用start方法,报错

进入到就绪状态的线程脱离程序员控制(谁先执行,谁后执行,是否交替等都由cpu决定。)

3.运行状态


一个处于就绪状态的线程被cpu调度了,就进入执行状态,开始执行run方法。

cpu调度:时间片轮换

如果时间片到了,保存当前正在执行的线程的状态,将线程送回到runnable状态,再次参与cpu时间片轮换。

4.阻塞状态

1.挂起:

1) 正在运行的线程调用sleep方法会放弃cpu的使用权利,进入到阻塞状态,不参与cpu抢占。不会释放拥有的资源。

正在sleep的线程timeout,或者被interrupt,那么会终止阻塞,进入到Runnable状态。

interrupt:中断线程(发送中断信号)

isInterrupted:判断线程的中断状态。

interrupted:static修饰的方法。判断线程的中断状态,同时清空中断信息。

2) 正在运行的线程调用其他线程的join方法之后,就放弃cpu的使用权,进入到阻塞状态,等到调用了join方法的线程执行结束之后再回到runnable状态参与cpu的轮换。这时进入阻塞状态的线程也不会放弃锁资源。

谁调用谁等待,调用谁等待谁

main{

rt1.join();

rt2.join();

}

main线程会等待rt1和rt2线程执行结束之后再执行。

2.锁池:

一个正在运行的线程遇见synchronized操作,需要申请锁资源,进入阻塞状态(对象的锁池)。不参与cpu的轮换。直到申请的锁资源可用,进入runnable状态。

3.等待池

正在运行的线程遇见wait操作,放弃cpu,进入阻塞状态(等待),进入阻塞状态的线程不再持有锁资源。等到notify/notifyAll,出wait状态,进入锁池等待

5.死亡状态:

当线程的run方法执行结束,线程进入死亡状态。进入死亡状态的线程是没办法转变成其他的状态。

控制线程的死亡:

1.stop:不推荐,不安全

2.interrupt: 中断线程,不推荐,会清除我们的中断状态,并收到一个中断异常。后续调用isInterrupted()和interrupted()方法判断状态时得不到正确的值。

3.设置标示变量。

共享标示:也可以用volatile来修饰该变量

//volatile保证了线程可以正确的读取其他线程写入的值

volatile boolean keepRunning = true;

1.extends Thread{

static 类变量

}

2.implements Runnable{

1.共享runnable:

1.实例变量

2.类变量

2.不同享Runnable:

2.类变量

}

start()

1.new ———> Runnable

cpu调度

2.runnable <——–>running

run完成

3.running ————-> Dead

sleep/join timeout/interrupt/joins

4.running ———->Block——————–>runnable

不释放锁资源

synchronized 申请的锁资源可用

5.running————-》阻塞—————–>runnable;

wait notify/notifyAll lock可用

6.running—->阻塞—————>锁池等待——>runnable

六、多线程并发访问的互斥问题。

java中每一个对象都有唯一的一把锁

临界区:操作共有数据时有可能会引起数据不一致结果的代码。

解决方案:

1.共有数据

2.找临界区

3.申请共有资源的锁。

note:对于临界区的控制越精确,线程的并发访问效率就越高。

1.synchronized :

1.方法体:{

1.实例方法

申请当前对象的锁

2.静态方法

申请镜像对象的锁

}

2.代码块:

synchronized( 公有对象 ){

}

七、并发访问线程之间的通信问题。

多个并发访问的线程谁先执行谁后执行。wait,notify/notifyAll

解决思路:

1.判断谁wait,谁notify

2.控制wait在notify(notifyAll)执行之前执行。

3.找到共有数据,基于共有数据的wait以及notify

八、死锁:

多个并发的线程出现资源的相互等待。

九、线程调度:

1.yield:线程让步,给调度程度发送一个暗示,当前线程要放弃cpu。然后直接回到runnable状态,参与cpu的轮换。

2.线程都具有等级,java将线程划分为1–10个等级。值越大等级越高,一般说高等级的线程比低等级的线程具有更高的执行概率。

扩展学习:

Happens-before原则

Locks和Condition对象,是对锁机制和等待条件的高层实现

线程的安全性:原子性和可见性

DeadLocks

多线程编程常用的交互模型:Producer-Consumer模型

Read-Write Lock模型

Future模型

Worker Thread模型

了解java5引入的并发编程工具:java.util.concurrent

线程池ExcutorService

Callable & Future

BlockingQueue
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  多线程 计算机