黑马程序员_多线程与死锁
来源:互联网 发布:网络搞笑猛虎下山图 编辑:程序博客网 时间:2024/06/05 20:14
------- android培训、java培训、期待与您交流! ----------
一、线程的创建
1、继承Thread类
创建步骤:
1、定义类继承Thread
2、复写Thread类中的run方法
3、调用线程的start方法
此方法有两个作用:
启动线程
调用run()方法
class Demo extends Thread//定义类继承Thread{ public void run()//复写run()方法 { for(int x=0; x<60; x++) System.out.println("Demo run()---"+x); }}class ThreadDemo{ public static void main(String[] args) { Demo d = new Demo();//创建一个线程 d.start();//开启线程,并调用线程的run()方法
for(int x=0; x<60; x++) System.out.println("Hello Thread!---"+x); }}
程序运行结果如下:
运行结果每一次都不同。
因为多个下次都要获取CPU的执行权,CPU执行到谁,谁就运行。
但是在某一时刻,只能有一个程序在运行。(多核除外)
多线程的一个特性,随机性。
2、实现Runnable接口
/*需求:简单的卖票程序,多个窗口同是卖票。
创建线程的第二种方式:实现Runnable接口
步骤:1、定义类实现Runnable接口2、覆盖Runnable接口中的run方法。 将线程要运行的代码存放在该run方法中。3、通过Thread类建立线程对象。4、将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。5、调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。
*/class Ticket implements Runnable{ private int tick = 100; public void run() { while (true) { if(tick>0) { System.out.println(Thread.currentThread().getName()+"---sale : "+tick--); } } }}class TicketDemo{ public static void main(String[] args) { Ticket t = new Ticket();
Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); }}
程序运行结果如下:
3、两种方法对比
实现方式和继承方式有什么区别?
实现方式好处:避免了单继承的局限性。
在定义线程时,建议使用实现方式。
两种方式区别:
继承Thread:线程代码存放在Thread子类run方法中。
实现Runnable:线程代码存放在接口的子类的run方法中。
二、多线程的安全问题
1、通过分析上述程序,发现存在安全隐患,可以通过代码进行验证。
class Ticket implements Runnable { private int tick = 100; public synchronized void run() { while (true) { if(tick>0) { //因为继承了接口,而接口中没有异常的抛出,所以只能try try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"---sale : "+tick--); } } }}
修改后运行结果出现以下情况:
出现问题原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还未执行完,另一个线程就进入执行,从而导致共享数据出错。2、JAVA对多线程安全问题有专业解决方式:同步代码块。synchronized(对象){ 需要被同步的代码}
具体代码如下:
class Ticket implements Runnable { //Object obj = new Object(); private int tick = 1000; public void run() { while (true) { synchronized(this) { if(tick>0) { //因为继承了接口,而接口中没有异常的抛出,所以只能try try{Thread.sleep(10);}catch(Exception e){} System.out.println(Thread.currentThread().getName()+"---sale : "+tick--); } } } }}class TicketDemo2{ public static void main(String[] args) { Ticket t = new Ticket();
Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); Thread t5 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); t5.start(); }}
代码修改后,运行结果中未出现为0等错误情况。
好像是CPU的缘故,在票数1000的时候,只能看到一个线程。当票数为10000的时候,方可看到其他线程运行的情况。
3、单例设计模式
/*单例设计模式
*///饿汗式class Single{ private static final Single s = new Single(); private Single(){} public static Single getInstance() { return s; }}
//懒汉式
//延迟加载单例模式class Single{ private static Single s = null; private Single(){} public static Single getInstance() { synchronized(Single.class)//通过锁确保程序在多线程访问时运行安全 { if(s==null) s = new Single(); } return s; }}
发现懒汉式中,如果有一个线程进入锁中,其它线程只能等待,会导致程序效率低,继续对其进行完善。
class Single{ private static Single s = null; private Single(){} public static Single getInstance() { if(s==null)//进行判断,如果不为空,就不需要等待锁。 { synchronized(Single.class) { if(s==null) s = new Single(); } } return s; }}
三、死锁的探讨
/*死锁形成探讨*/class Test implements Runnable{ private boolean flag; Test(boolean flag)//建立标识,让两个线程分别运行。 { this.flag = flag; } public void run()//锁相互嵌套,形成各自占用资源,同时需要对方资源。 { if (flag) { synchronized(MyLock.LockA) { System.out.println("if LockA"); synchronized(MyLock.LockB) { System.out.println("if LockB"); } } } else { synchronized(MyLock.LockB) { System.out.println("else LockB"); synchronized(MyLock.LockA) { System.out.println("else LockA"); } } } }}class MyLock//创建两个锁{ static Object LockA = new Object(); static Object LockB = new Object();}class DeadLockDemo{ public static void main(String[] args) { Thread t1 = new Thread(new Test(true));//创建线程t1 Thread t2 = new Thread(new Test(false));//创建线程t2
t1.start(); t2.start(); }}
程序运行结果如下:可见:两个线程分别只运行了第一输出语句,便形成了死锁。
----------- android培训、java培训、期待与您交流! --------------
详细请查看:http://edu.csdn.net/heima/
- 黑马程序员_多线程与死锁
- 黑马程序员_多线程死锁
- 黑马程序员_多线程(死锁)
- 黑马程序员_多线程之死锁
- 黑马程序员-多线程死锁
- 黑马程序员_多线程的死锁和等待唤醒机制
- 黑马程序员_线程死锁
- 黑马程序员_多线程与并发
- 黑马程序员-JAVA基础-多线程的安全、同步与死锁
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_多线程
- 黑马程序员_排序
- Spring Data MongoDB简单的增删改查
- C#绘制验证码噪声点
- 【Python】pip - 安装第三方包的神器
- blktrace 深度了解linux系统的IO运作
- 黑马程序员_多线程与死锁
- 配置Apache服务器
- json字符串在javascript和java代码中的表示方式
- 黑马程序员_位运算符的应用
- 收集一些画图方面的js库
- 【Android】注解使用注意事项
- UFT的使用
- LGame学习笔记2-----使用Sprite类绘制人物
- Effective Unity3D