Java编程之多线程死锁与线程间通信简单实现代码
死锁定义
死锁是指两个或者多个线程被永久阻塞的一种局面,产生的前提是要有两个或两个以上的线程,并且来操作两个或者多个以上的共同资源;我的理解是用两个线程来举例,现有线程A和B同时操作两个共同资源a和b,A操作a的时候上锁LockA,继续执行的时候,A还需要LockB进行下面的操作,这个时候b资源在被B线程操作,刚好被上了锁LockB,假如此时线程B刚好释放了LockB则没有问题,但没有释放LockB锁的时候,线程A和B形成了对LockB锁资源的争夺,从而造成阻塞,形成死锁;具体其死锁代码如下:
public class MyDeadLockTest { public static void main(String[] args){ Object obj1 = new Object(); Thread thread1 = new Thread(new DeadRes(true,obj1)); Thread thread2 = new Thread(new DeadRes(false,obj1)); thread1.start(); thread2.start(); } } class DeadRes implements Runnable{ boolean flag; Object obj; public DeadRes(boolean flag, Object obj1) { this.flag = flag; this.obj = obj1; } @Override public void run() { if(flag){ synchronized (DeadRes.class){ System.out.println(Thread.currentThread().getName()+" acquie lock is DeadRes.class"); synchronized (obj){ System.out.println(Thread.currentThread().getName()+" acquie lock is obj"); } } }else{ synchronized (obj){ System.out.println(Thread.currentThread().getName()+" acquie lock is obj"); synchronized (DeadRes.class){ System.out.println(Thread.currentThread().getName()+" acquie lock is DeadRes.class"); } } } } }
执行结果如下图:
Thread-1 acquie lock is obj Thread-0 acquie lock is DeadRes.class
当然每次执行的结果不一样,有可能是一种和谐状态,没有发生死锁,此时为保证每次死锁,可以让run()方法中,执行while(true)循环,这样保证了每次必定发生死锁;当然实际应用中,我们应该尽量避免死锁,当有多线程操作多个共同资源的时候,避免发生同一锁对象的同步嵌套。
线程间的通讯—-生产者与消费者模式
1、让两个线程交替进行操作,当生产了一个数字后,紧接着消费一个,首先采用Object对象中的wait-notify来实现,具体代码如下:
public class ThreadProConsume { public static void main(String[] args){ Product product = new Product(); Thread thread1 = new Thread(new Producer(product)); Thread thread2 = new Thread(new Consumer(product)); thread1.start(); thread2.start(); } } class Product{ String name; private int count = 1; boolean flag = false; public synchronized void set(String name){ if(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name +"--"+count++; flag = true; System.out.println(Thread.currentThread().getName()+" produce num : "+this.name); this.notify(); } public synchronized void out(){ if(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" consume num is : "+this.name); flag = false; this.notify(); } } class Producer implements Runnable{ Product res; public Producer(Product product) { this.res = product; } @Override public void run() { while(true){ res.set("guyue"); } } } class Consumer implements Runnable{ Product res; public Consumer(Product product) { this.res = product; } @Override public void run() { while(true){ res.out(); } } }
执行结果如图:
Thread-1 consume num is : guyue--3938 Thread-0 produce num : guyue--3939 Thread-1 consume num is : guyue--3939 Thread-0 produce num : guyue--3940 Thread-1 consume num is : guyue--3940 Thread-0 produce num : guyue--3941 Thread-1 consume num is : guyue--3941
当超过两个以上线程操作的时候,这里需要在set()与out()方法中的if判断改为while,并且notif方法,改为notifyAll(),这样多个线程操作的时候,便可以交替进行,具体代码如下:
public class ThreadProConsume { public static void main(String[] args){ Product product = new Product(); Thread thread1 = new Thread(new Producer(product)); Thread thread3 = new Thread(new Producer(product)); Thread thread2 = new Thread(new Consumer(product)); Thread thread4 = new Thread(new Consumer(product)); thread1.start(); thread3.start(); thread2.start(); thread4.start(); } } class Product{ String name; private int count = 1; boolean flag = false; public synchronized void set(String name){ while(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name +"--"+count++; flag = true; System.out.println(Thread.currentThread().getName()+" produce num : "+this.name); this.notifyAll(); } public synchronized void out(){ while (!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName()+" consume num is : "+this.name); flag = false; this.notifyAll(); } }
执行结果如下:
Thread-0 produce num : guyue--50325 Thread-2 consume num is : guyue--50325 Thread-1 produce num : guyue--50326 Thread-3 consume num is : guyue--50326 Thread-0 produce num : guyue--50327 Thread-2 consume num is : guyue--50327 Thread-1 produce num : guyue--50328 Thread-3 consume num is : guyue--50328
2、采用Lock-Condition方法实现如下:
class Product{ String name; private int count = 1; boolean flag = false; Lock lock = new ReentrantLock(); Condition conditon = lock.newCondition(); public void set(String name){ try{ lock.lock(); while(flag){ conditon.await(); } this.name = name +"--"+count++; flag = true; System.out.println(Thread.currentThread().getName()+" produce num : "+this.name); conditon.signalAll(); }catch (Exception e){ }finally { lock.unlock(); } } public void out(){ try{ lock.lock(); while(!flag){ conditon.await(); } flag = false; System.out.println(Thread.currentThread().getName()+" consumer num is : "+this.name); conditon.signalAll(); }catch (Exception e){ }finally { lock.unlock(); } } }
执行结果如下:
Thread-0 produce num : guyue--20305 Thread-3 consumer num is : guyue--20305 Thread-1 produce num : guyue--20306 Thread-2 consumer num is : guyue--20306 Thread-0 produce num : guyue--20307 Thread-3 consumer num is : guyue--20307 Thread-1 produce num : guyue--20308 Thread-2 consumer num is : guyue--20308
以上就是本文关于Java编程之多线程死锁与线程间通信简单实现代码的全部内容,希望对大家有所帮助。关于Java多线程以及线程间通信的例子,本站还有几篇文章可以参考:
详解java中的互斥锁信号量和多线程等待机制、Java多线程编程小实例模拟停车场系统、Java网络编程基础篇之单向通信
如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!
栏 目:Java编程
下一篇:解析Java编程之Synchronized锁住的对象
本文地址:https://www.xiuzhanwang.com/a1/Javabiancheng/8442.html
您可能感兴趣的文章
- 01-10Java咖啡馆(1)——叹咖啡
- 01-10Java Socket编程(三) 服务器Sockets
- 01-10Java进阶:Struts多模块的技巧
- 01-10Java Socket编程(一) Socket传输模式
- 01-10Java Socket编程(二) Java面向连接的类
- 01-10Java运行时多态性的实现
- 01-10Java经验点滴:处理没有被捕获的异常
- 01-10Java Socket编程(四) 重复和并发服务器
- 01-10Java中的浮点数分析
- 01-10面向对象编程:Java中的抽象数据类型
阅读排行
本栏相关
- 01-10Java咖啡馆(1)——叹咖啡
- 01-10JVM的垃圾回收机制详解和调优
- 01-10Java Socket编程(三) 服务器Sockets
- 01-10Java进阶:Struts多模块的技巧
- 01-10J2SE 1.5版本的新特性一览
- 01-10Java Socket编程(一) Socket传输模式
- 01-10Java运行时多态性的实现
- 01-10Java Socket编程(二) Java面向连接的类
- 01-10Java Socket编程(四) 重复和并发服务
- 01-10Java经验点滴:处理没有被捕获的异常
随机阅读
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 08-05织梦dedecms什么时候用栏目交叉功能?
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 04-02jquery与jsp,用jquery
- 01-10SublimeText编译C开发环境设置
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-11ajax实现页面的局部加载
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 01-10C#中split用法实例总结
- 01-10delphi制作wav文件的方法