T10线程锁以及死锁.docx
《T10线程锁以及死锁.docx》由会员分享,可在线阅读,更多相关《T10线程锁以及死锁.docx(11页珍藏版)》请在冰豆网上搜索。
![T10线程锁以及死锁.docx](https://file1.bdocx.com/fileroot1/2023-2/9/381ffca4-e64c-4dcd-8166-2121ce3b021c/381ffca4-e64c-4dcd-8166-2121ce3b021c1.gif)
T10线程锁以及死锁
线程,锁,以及死锁
考察点:
java中创建线程的两种方法,并启动线程
java中线程的各种操作方法
java中如何实现线程同步
必会代码
1.线程的定义
packagethread;
publicclassSoundThreadextendsThread{
publicvoidrun(){
while(true){
System.out.println(Thread.currentThread().getName()+"在跳舞...");
try{
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
2.线程的启动方法一
packagethread;
publicclassThread1{
publicstaticvoidmain(String[]args){
SoundThreadt=newSoundThread();
t.setName("xxx");
t.start();//启动线程
while(true){
System.out.println(Thread.currentThread().getName()+"在歌唱祖国。
。
。
。
");
try{
Thread.sleep(1000);//让程序睡眠多少毫秒
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
3。
线程的启动方法二
packagethread;
publicclassSoundDemoimplementsRunnable{
publicvoidrun(){
while(true){
System.out.println("跳也跳....");
try{
Thread.sleep(500);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
publicstaticvoidmain(String[]args){
SoundDemos=newSoundDemo();
Threadt=newThread(s);
t.start();
}
}
1.通过两个线程分别实现输出,一个线程输出大写A-Z,另一个线程输出小写a-z,且交互输出
说明解答步骤,每步的含义及解析
通过两个线程分别实现输出,一个线程输出大写A-Z,另一个线程输出小写a-z,且交互输出
运行结果如下:
技术分析
a.实现线程的方法有两种,实现Runnable接口与继承Thread类,当然继承父类简单些
b.不管是继承父类还是实现接口,都需要实现run()方法
c.启动线程的时候是调用start()方法,而不能直接调用run()方法
d.如果要想让两个线程实现交替输出的话,一般来说需要让线程在执行过程中暂停执行一段时间,这样其他线程才有可能得到执行的机会
程序参考
扩展
上面的案例是通过继承Thread来实现的,那么请改写成通过实现Runnable接口实现
2.同时启动两个线程,调用同一个类中的两个方法,分别打印出0—100和101到200之间的数字,且要求数字打印不能交互
同时启动两个线程,调用同一个类中的两个方法,分别打印出0—100和101到200之间的数字,且要求数字打印不能交互
程序运行如下:
技术分析
a.同步对象使用的场合是在多个线程同时方法一个对象的时候。
因此输出打印的方法实现应该写在一个类中。
b.线程同步有两种实现方法:
方法级同步与代码块同步。
不管使用那种同步方法都需要共享相同的资源:
同一个打印类的对象
程序参考
a.创建一个打印类
b.通过继承Thread类实现线程A
c.通过继承Thread类实现线程B
d.写测试类
e.扩展
将以上的实现方法改写成通过实现接口创建线程,并实现同步。
锁
以卖票为例子,以下例子要求自己能够默写出来,给下面的代码加上注释
packagethread;
publicclassSaleTicketextendsThread{
staticintticket=1000;
staticObjecto=null;
publicvoidrun(){
while(true){
synchronized(o){
if(ticket>0){
ticket--;
System.out.println(Thread.currentThread().getName()+"卖了一张票,剩下"+ticket);
}
else{
System.out.println("票已售完..");
break;
}
}
try{
Thread.sleep(100);
}catch(InterruptedExceptione){
e.printStackTrace();//打印错误信息
}
}
}
}
packagethread;
publicclassSaleTicketTest{
publicstaticvoidmain(String[]args){
SaleTickett1=newSaleTicket();
t1.setName("南门口售票点");
t1.start();
SaleTickett2=newSaleTicket();
t2.setName("安居售票点");
t2.start();
SaleTickett3=newSaleTicket();
t3.setName("三康庙售票点");
t3.start();
SaleTickett4=newSaleTicket();
t4.setName("赣县售票点");
t4.start();
SaleTickett5=newSaleTicket();
t5.setName("火车站售票点");
t5.start();
}
}
总结
多线程:
1、实现多线程方式:
1>继承Thread类重写run()方法
启动线程:
实例化该线程对象,然后调用该对象的start()启动
SaleTickett=newSaleTicket();
t.start();
2>实现Runnable接口复盖run()方法
启动线程:
实例化线程对象,在实例化Thread类并将线程对象作为参数传递给Thead类,最后调用Thread.start();启动
SaleTickets=newSaleTicket();
Threadt=newThread(s);
t.start();
2、线程加锁:
synchronized(钥匙){
被加锁的代码
}
必会考题
1.编写一个线程类,启动10条线程同时执行该类,要求输出效果如下所示
001
002
003
….
999
2.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法?
如果方法是同步方法则不可以。
因为当synchronized出现在方法上时,表示使用对象本身作为同步对象(锁),一旦进入了一个synchronized方法后,该对象被占用,所有使用对象本身作为同步对象的代码块/方法都进不去。
3.sleep()和wait()有什么区别?
sleep():
线程主动放弃CPU,使得线程在指定的时间内进入阻塞状态,不能得到CPU时间,指定的时间一过,线程重新进入可执行状态。
典型地,sleep()被用在等待某个资源就绪的情形:
测试发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止。
wait():
与notify()配套使用,wait()使得线程进入阻塞状态,它有两种形式,一种允许指定以毫秒为单位的一段时间作为参数,另一种没有参数,当指定时间参数时对应的notify()被调用或者超出指定时间时线程重新进入可执行状态,后者则必须对应的notify()被调用
4.方法级同步的实现原理
当调用对象的同步方法时,线程取得对象锁(lock)或监视器;如果另一个线程试图执行任何同步方法时,他就会发现他被锁住了,进入挂起状态,直到对象监视器上的锁被释放时为止。
当锁住方法的线程从方法中返回时,只有一个排队等候的线程可以访问对象
5.代码块级同步实现原理
在进入同步代码前,必须得到object对象的锁,如果其他线程已经得到这个锁,那么就得等到锁被释放后才能进入临界区。
6.同步中锁的特性
1、锁是基于一个特定对象的,而不是特定的方法。
2、锁的作用域(scopefoalock):
从锁被获取到被释放的时间。
在同步方法中,锁的作用域就是方法运行的时间,这被称为方法的作用域
3、在java中系统中的每个对象都会默认的创建一个锁。
对象中的同步方法将共享该对象锁。
要执行同步化的方法,线程得先获得锁,当该线程结束后,无论是正常返回还是因其他异常返回,都会释放该锁。