1.进程和线程的区别
进程是程序的一次执行过程,是一段完整的程序
线程是进程中的执行一段程序片段
2.为什么多线程的作用是什么,为什么要用多线程。
Windows程序基于消息循环的。如果要做多件事,你就得排队,这叫消息列队。单线程程序执行效率相对较低。多线程相当于多个消息循环。可以把多件事情放到不同的循环中去完成。效率高
3.线程的生命周期
初始--可运行--阻塞--不可运行--死亡
休眠:线程快执行完run方法后不让该线程死亡,可使其进入休眠。不占用系统资源,sleep(time)方法进入休眠
阻塞:指的是暂停一个线程的执行以等待某个条件发生(如某资源就绪)
(注):一般阻塞或线程暂停后再唤醒后都回到就绪状态
wait(),notify()和resume(),suspend()方法使线程阻塞和恢复
区别是resume()和suspend()阻塞时不会释放占用的锁
wait(),notify()属于Object类,
resume(),suspend()是Thread类的方法
五种情况可能造成线程阻塞:
1.调用sleep()进入休眠状态
2.调用suspend()暂停了线程的执行
3.用wait()暂停了线程的执行
4.线程正在等待一些IO操作完成
5.线程试图调用另一个对象的"同步"方法
4.线程同步与锁机制
当多个线程访问同一个对象时,为了避免数据的错误,所以出现了线程同步锁机制。
比如A和B同时对一个银行卡号进行存钱的操作。银行卡里本来有500,A存1000,B存500. 最后结果应该是2000才对,但是由于同时存钱有可能就会出系统错误,最后结果变成了1500,A看结果没错,但是B看到自己只存了500,却多出了500块。实际上系统吞了500.
同步锁的原理:java中每个对象都有一个内置同步锁。java中可以使用synchronized关键字来取得一个对象的同步锁。syschronized的使用方式:
1.synchronized用来标识一个普通方法时,表示一个线程要执行该方法,必须取得该方法所在的对象锁
public synchronized void getM(){
//标识方法
}
2.synchronized修饰一个代码块。表示一个线程要执行该代码块,必须获得obj锁。这样做的目的是减小锁的粒度,保证当不同块所需的锁不冲突时不用对整个对象加锁。
在一段代码中,加上synchronized(object){...}
public void method()
{
// … …
synchronized(this)
{
// … …
}
}
5.实现多线程的方式
1.继承Thread类,实现Runnable接口
public class TestThread extends Thread{
}
public class TestThread2
implements Runnable{
}
区别:
1.继承Thread类有局限性,因为只能继承1个类,而可以实现多个接口。而Thread也是实现了Runnable接口
2.适用于资源共享
继承Thread是多个线程分别完成自己的任务,比如3个卖票的(3个线程),3个人分别去卖10张票
实现Runnable接口是多个线程同时完成一项任务,比如3个卖票的(3个线程),同时去卖10张票
实现多线程:
C:\Users\DELL PC\Desktop\THREAD.jpg
打印结果是:
B0次
A0次
B1次
A1次
B2次
A2次
B3次
A3次
B4次
A4次
虽然说多线程是同时进行,但实际上也是根据分配到Cpu的资源来执行的,因为Cpu执行的速度太快,所以就好像多个线程在同时执行一样。
为什么这里实现的方法是Run()方法而最终开始一个线程是调用start():
开始线程时调用Run和start的区别:
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。
然后通过此Thread类调用方法run()来完成其运行操作,这里的方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程终止,而Cpu再运行其他线程。
而如果直接调用run方法,这只是相当于调用一个普通的方法而已,程序中依然只有这一个线程,其程序执行路径还是只有一条,这样就没有达到写线程的目的。 |