黑马程序员——多线程

进程和线程

-----------android培训java培训、java学习型技术博客、期待与您交流!------------  

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以有多个线程。比如在Windows系统中,一个运行的xx.exe就是一个进程。

Java程序的进程里有几个线程:主线程,垃圾回收线程(后台线程)

线程是指进程中的一个执行任务(控制单元),一个进程中可以运行多个线程,多个线程可共享数据。

多进程:操作系统中同时运行的多个程序;

多线程:在同一个进程中同时运行的多个任务;

一个进程至少有一个线程,为了提高效率,可以在一个进程中开启多个控制单元。 

并发运行。如:多线程下载软件。 

可以完成同时运行,但是通过程序运行的结果发现,虽然同时运行,但是每一次结果都不一致。 

因为多线程存在一个特性:随机性。 

造成的原因:CPU在瞬间不断切换去处理各个线程而导致的。 

可以理解成多个线程在抢cpu资源。 

 

总结:

多线程下载:此时线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开起好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配。不难理解,如果你线程多的话,那下载的越快。现流行的下载软件都支持多线程。

 

多线程是为了同步完成多项任务,不是为了提供运行效率,通过提高资源使用效率来提高系统的效率.

线程是在同一时间需要完成多项任务的时候实现的.

 

 

线程与进程的比较

 

线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元;而把传统的进程称为重型进程(Heavy—WeightProcess),它相当于只有一个线程的任务。在引入了线程的操作系统中,通常一个进程都有若干个线程,至少需要一个线程。

 

进程与线程的区别:

       1.进程有独立的进程空间,进程中的数据存放空间(堆空间和栈空间)是独立的。

       2.线程的堆空间是共享的,栈空间是独立的,线程消耗的资源也比进程小,相互之间可以影响的。

 

线程的二种创建方式

创建线程的第一种方式:继承Thread ,由子类复写run方法。

步骤:

1,定义类继承Thread类;

2,目的是复写run方法,将要让线程运行的代码都存储到run方法中;

3,通过创建Thread类的子类对象,创建线程对象;

4,调用线程的start方法,开启线程,并执行run方法。

线程状态:

新建:start()

运行:具备执行资格,同时具备执行权;

冻结:sleep(time),wait()—notify()唤醒;线程释放了执行权,同时释放执行资格;

临时阻塞状态:线程具备cpu的执行资格,没有cpu的执行权;

消亡:stop()

创建线程的第二种方式:实现一个接口Runnable。

步骤:

1,定义类实现Runnable接口。

2,覆盖接口中的run方法(用于封装线程要运行的代码)。

3,通过Thread类创建线程对象;

4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类中的构造函数。

为什么要传递呢?因为要让线程对象明确要运行的run方法所属的对象。

5,调用Thread对象的start方法。开启线程,并运行Runnable接口子类中的run方法。

Ticket t = new Ticket();

/*

直接创建Ticket对象,并不是创建线程对象。

因为创建对象只能通过new Thread类,或者newThread类的子类才可以。

所以最终想要创建线程。既然没有了Thread类的子类,就只能用Thread类。

*/

Thread t1 = new Thread(t); //创建线程。

/*

只要将t作为Thread类的构造函数的实际参数传入即可完成线程对象和t之间的关联

为什么要将t传给Thread类的构造函数呢?其实就是为了明确线程要运行的代码run方法。

*/

总结:

为什么要覆盖run方法呢?

Thread类用于描述线程。该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法.

也就是说Thread类中的run方法,用于存储线程要运行的代码。

 

多线程安全问题的原因

通过图解:发现一个线程在执行多条语句时,并运算同一个数据时,在执行过程中,其他线程参与进来,并操作了这个数据。导致到了错误数据的产生。

涉及到两个因素:

1,多个线程在操作共享数据。

2,有多条语句对共享数据进行运算。

原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。

解决安全问题的原理

只要将操作共享数据的语句在某一时段让一个线程执行完,在执行过程中,其他线程不能进来执行就可以解决这个问题。

如何进行多句操作共享数据代码的封装呢?

java中提供了一个解决方式:就是同步代码块。

格式:

synchronized(对象){  // 任意对象都可以。这个对象就是锁。

需要被同步的代码;

}

Synchronized(自己得会写得出)

两种进程创建方式比较

A extends Thread:

简单

不能再继承其他类了(Java单继承)

同份资源不共享

A implements Runnable:(推荐)

多个线程共享一个目标资源,适合多线程处理同一份资源。

该类还可以继承其他类,也可以实现其他接口。

 

总结:

实现方式,因为避免了单继承的局限性,所以创建线程建议使用第二种方式。

什么时候产生死锁,该怎么办?

前提:多个线程(操作数据的共享数据都要同步),是否同一个锁

Interrupt

setDaemon设置为守护线程

join让当前主线程停下等谁的join

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值