您的位置:首页 > 编程语言 > Java开发

Java中的线程

2015-11-23 12:25 495 查看
程序 进程 线程

程序:program,是一个静态的概念

进程:process,是一个动态的概念

*进程是程序的一次动态执行过程,占用特定的地址空间

*每个进程都是独立的,有三部分组成cpu,data,code

*缺点:内存的浪费,CPU的负担

线程:Thread,是进程中一个“单一的连续控制流程”(a single sequential flow of

contral)/执行路径

*线程又被称为轻量级进程

*Threads run at the same time,independently of one another

*一个进程可拥有多个并行的线程

*一个进程中的线程共享相同的内存单元/内存地址空间->可以访问相同的变量和对象,而

且他们从同一对中分配对象->通信、数据交换、同步操作

*由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得

通信更简便而且信息传递的速度也更快。

线程和进程的区别

根本区别:进程是资源分配的基本单位,线程是调度和执行的单位

包含关系:没有线程的进程是可以被看做单线程的,如果一个进程内拥有多个线程,则执

行过程不是一条线程,而是多条线程共同完成的。

线程是进程的一部分,所以线程被称为轻量级进程。

java实现多线程

在java中负责线程的这个功能的是Java.lang.Thread这个类

可以通过创建Thread的实例来创建新的线程

每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称

为线程体

通过调用Thread类的start()方法来启动一个线程

继承Thread类的方式的缺点:那就是如果我们的类已经从一个类继承(如小程序必须继承

自Applet类),则无法继承Thread类

通过Runnable接口实现多线程

优点:可以同时实现继承。实现Runnable接口方式要通用一些

1)避免单继承

2)方便共享资源,同一份资源,多个代理访问

* 静态代理模式

* 1.真实角色

* 2.代理角色,持有真实角色的引用

* 3.二者实现相同的接口

通过Callable接口实现多线程

优点:可以获取返回值

Callable 和 Future

Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被

其他线程执行的任务。

Callable和Runnable有几点不同

1)Callable规定的方法是call(),而Runnable规定的方法是run()

2)Call()方法可抛出异常,而run()方法是不可能抛出异常的

3)Callable的任务执行后可返回值,运行Callable任务可拿到一个Future对象,而

Runnable的任务是不能返回值的。

Future表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成 ,

并检索计算的结果。

通过Future对象可了解任务执行情况,可取消任务的执行,还可获取执行的结果

缺点:繁琐

思路:

1)创建Callable实现类+重写call

2)借助 执行调度服务ExecutorSerVice,获取Future对象

ExecutorService ser=Executors.newFixedThreadPool(2);

3)获取值 result.get()

4)停止服务 ser.shutdownNow();

方法一:继承Thread+run();

启动:创建子类对象+对象.start()

方法二:实现Runnable+run()

启动:使用静态代理

1、创建真实角色

2、创建代理角色+引用

3、代理角色.start();

推荐使用接口

1.避免单继承局限性

2.便于共享资源

线程状态

1.新生状态:用new关键字和Thread类或其子类建立一个线程对象后,该线程就处于新生

状态。处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态

(runnable)

2.就绪状态:处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程

就绪队列,等待系统为其分配CPU。等待状态并不是执行状态,当系统选定一个等待执行

的Thread对象后,他就会从等待执行状态进入执行状态,系统挑选的动作称之为“CPU调

度”。一旦获得CPU,线程就进入运行状态并自动调用自己的run方法

3.运行状态

4.阻塞状态:处于运行状态的线程在某些情况下。如执行了sleep方法,或等待I/O设备等

资源,将让出CPU并暂时停止自己的执行,或进入阻塞状态。在阻塞状态的线程不能进入

就绪对垒。只有当引起阻塞的原因消除时,线程便转入就绪状态,重新到就绪队列中排队

等待,被系统选中后从原来停止的位置开始继续执行。

5.死亡状态

停止线程

1.自然终止

2.外部干涉:

1)线程类中 定义线程体使用的标识

2)线程体使用该标识

3)提供对外的方法改变该标识

4)外部根据条件调用该方法即可

阻塞

join():合并线程 等待该线程终止

yield():暂停自己的线程,静态方法static 写在哪个线程中就暂停谁

sleep():休眠 暂停当前线程 static 不释放锁 与时间相关 数数 倒计时 模拟网络

延时

线程的基本信息

isAlive() 判断是否还“活”着,即进程是否还未终止。

getPriority() 获得线程的优先级数值

setPriority() 设置线程的优先级数值

setName() 给线程一个名字

getName() 取得线程的名字

currentThread() 取得当前正在运行的线程对象也就是取得自己本身

priority常量(代表的是概率)不是绝对的先后顺序

MAX_PRIORITY

NORM_PRIORITY

MIN_PRIORITY

线程同步(并发)

由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这

个严重的问题。Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被

多个线程同时访问。

由于我们可以通过private关键字来保证数据对象只能被方法访问,所以我们只针对方法

提出一套机制,这套机制就是synchronized关键字,它包括两种用法:synchronized方法

和synchronized块。

同步块

synchronized(引用类型|this|类.class){

}

同步方法

synchronized

单例设计模式

确保一个类只有一个对象

懒汉式 double check

1、构造器私有化,避免外部直接创建对象

2、声明一个静态变量

3、创建一个对外的公共的静态方法访问该变量,如果变量没有对象,创建该对象

class Jvm{

private static Jvm ins;

private Mjvm(){

}

public static getIns(){

if(null==ins){

synchronized(Jvm.class){

if(null=ins){

ins=new jvm();

}

}

}

}

return ins;

}

饿汉式

1、构造器私有化,避免外部直接创建对象

2、声明一个静态变量,同时创建该对象

3、创建一个对外的公共的静态方法访问该变量

死锁:过多的同步容易造成死锁

一个场景,共同的资源

生产者消费模式 信号灯法

wait() :释放锁

sleep():不释放锁

notify():唤醒

Timer定时器了类

TimerTask任务类

通过java timer timetask

spring的任务调度就是通过它们来实现的)

在这种实现方式中,Timer类实现的是类似闹钟的功能,也就是定时或者每个一定时间触

发一次线程。其实,Timer类本身实现的就是一个线程,只是这个线程是用来实现调用其

他线程的。而TimerTask类是一个抽象类,该类实现了Runnable接口,所以按照前面的介

绍,该类具备多线程的能力。

在这种实现方式中,通过集成TimerTask使该类获得多线程的能力,将需要多线程执行的

代码书写在run方法内部,然后通过Timer类启动线程的执行。

在实际使用时,一个Timer类可以启动任意多个TimerTask实现的线程,但是多个线程之间

存在阻塞。所以如果多个线程之间如果需要完全独立运行的话,最好还是一个Timer启动

一个TimerTask实现。

schedule( );

总结

一、线程创建

1.继承 Thread

2.实现 Runnable

3.实现 Callable(了解)

二、线程的创建

1、新生->start->就绪->运行->阻塞->终止

2、终止线程

3、阻塞: join yield sleep

三、线程的信息

1.Thread.currentThread

四、同步:对同一份资源

synchronized(引用类型变量|类.class|this)

修饰符 synchronized 方法的签名{

方法体

}

过多的同步可能造成死锁

五、生产者消费者模式

六、任务调度
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: