今天看到一个题:两个线程交替打印奇数和偶数,即一个线程打印奇数,另一个打印偶数,交替打印从1到100。想了下有多重实现方法。

wait和notify方法:

  1. public class OddEven {
  2.  
  3. private static int i = 1;
  4.  
  5. private static Object o = new Object();
  6.  
  7. private static class MyThread extends Thread {
  8. MyThread(String name) {
  9. super(name);
  10. }
  11.  
  12. public void run() {
  13. try {
  14. synchronized (o) {
  15. while (i < 100) {
  16. System.out.println(this.getName() + i++);
  17. o.notify();
  18. o.wait();
  19. }
  20. o.notify();
  21. }
  22. System.out.println(this.getName() + " over");
  23. } catch (Exception e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28.  
  29. public static void main(String[] args) {
  30. new MyThread("奇 ").start();
  31. new MyThread("偶 ").start();
  32.  
  33. }
  34. }

---

输出:

奇 1
偶 2
奇 3
偶 4
奇 5
偶 6
奇 7

...

LockSupport实现

  1. public class OddEvenLockSupport {
  2.  
  3. private static int i = 1;
  4.  
  5. private static Thread t1 = new MyThread1();
  6. private static Thread t2 = new MyThread2();
  7.  
  8. public static void main(String[] args) {
  9. t1.start();
  10. t2.start();
  11. }
  12.  
  13. private static class MyThread1 extends Thread {
  14. @Override
  15. public void run() {
  16. while (i < 51) {
  17. System.out.println("奇 " + i++);
  18. LockSupport.unpark(t2);
  19. LockSupport.park();
  20. }
  21. System.out.println(getName() + " over");
  22. LockSupport.unpark(t2);
  23. }
  24.  
  25. }
  26.  
  27. private static class MyThread2 extends Thread {
  28. @Override
  29. public void run() {
  30. while (i < 51) {
  31. LockSupport.park();//顺序很重要
  32. System.out.println("偶 " + i++);
  33. LockSupport.unpark(t1);
  34. }
  35. System.out.println(getName() + " over");
  36. LockSupport.unpark(t1);
  37. }
  38.  
  39. }
  40. }

---

使用Condition

  1. public class OddEven2 {
  2.  
  3. private static Lock lock = new ReentrantLock();
  4. static Condition even_c = lock.newCondition();
  5. static Condition odd_c = lock.newCondition();
  6.  
  7. private static class Odd extends Thread {
  8. public void run() {
  9. int odd = 1;
  10. try {
  11. lock.lock();
  12. while (odd < 100) {
  13. System.out.println("奇 " + odd);
  14. odd += 2;
  15. even_c.signal();
  16. odd_c.await();
  17. }
  18. System.out.println("奇 over");
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. } finally {
  22. even_c.signal();
  23. lock.unlock();
  24. }
  25. }
  26. }
  27.  
  28. private static class Even extends Thread {
  29. public void run() {
  30. int even = 0;
  31. try {
  32. lock.lock();
  33. while (even < 100) {
  34. System.out.println("偶 " + even);
  35. even += 2;
  36. odd_c.signal();
  37. even_c.await();
  38. }
  39. System.out.println("偶 over");
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. } finally {
  43. odd_c.signal();
  44. lock.unlock();
  45. }
  46. }
  47. }
  48.  
  49. public static void main(String[] args) {
  50. new Even().start();
  51. new Odd().start();
  52. }
  53. }

---

另一个题,写出会导致死锁的代码:

  1. public class DeadLock extends Thread {
  2. private Object lock1;
  3. private Object lock2;
  4.  
  5. public DeadLock(Object o1, Object o2) {
  6. this.lock1 = o1;
  7. this.lock2 = o2;
  8. }
  9.  
  10. public void run() {
  11. synchronized (lock1) {
  12. try {
  13. TimeUnit.MILLISECONDS.sleep(500);
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. }
  17. synchronized (lock2) {
  18. Q.p("end");
  19. }
  20. }
  21. }
  22.  
  23. public static void main(String[] args) {
  24. Object o1 = new Object(), o2 = new Object();
  25. new DeadLock(o1, o2).start();
  26. new DeadLock(o2, o1).start();
  27. Q.p("main end");
  28. }
  29. }

---

基础回顾:

每个Java对象都拥有一个锁标记,即monitor(监视器),称为对象锁。

wait:

调用obj.wait()方法会阻塞当前线程,直到另一线程调用obj.notify()或obj.notifyAll()方法,其中obj为同一对象,当前线程必须持有obj对象锁,即必须在synchronized方法或代码块中,否则抛出IllegalMonitorStateException。调用wait方法的线程会释放对象锁。

notify:

唤醒一个正在等待该对象锁的线程,若有多个线程都在等待也只会唤醒一个。被唤醒的线程无法立即执行,直到当前线程放弃该对象锁,然后被唤醒的线程会像往常一样与任何其他线程竞争该对象锁,

该方法也必须在持有该对象锁的线程里调用,即必须在synchronized方法或代码块中,否则抛出IllegalMonitorStateException。

synchronized:

synchronized关键字标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。

end

Java并发 两个线程交替执行和死锁的更多相关文章

  1. 简单的线程同步问题:两个线程交替执行N次【Synchronized、Lock、ArrayBlockingQueue】

    方法一:传统的线程方法import org.apache.log4j.Logger; /** * 两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象.<br/> * ...

  2. 面试必问!Java 多线程中两个线程交替执行,一个输出偶数,一个输出奇数

    前言 楼主今天在面经上看到这个题,挺有意思,小小的题目对多线程的考量还挺多.大部分同学都会使用 synchronized 来实现.楼主今天带来另外两种优化实现,让你面试的时候,傲视群雄! 第一种 sy ...

  3. 使用Java线程并发库实现两个线程交替打印的线程题

    背景:是这样的今天在地铁上浏览了以下网页,看到网上一朋友问了一个多线程的问题.晚上闲着没事就决定把它实现出来. 题目: 1.开启两个线程,一个线程打印A-Z,两一个线程打印1-52的数据. 2.实现交 ...

  4. Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  5. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  6. Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)

    Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...

  7. Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  8. Java并发编程:线程池的使用(转)

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  9. Java并发编程:线程控制

    在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...

随机推荐

  1. JavaWeb Session

    1. Session概述 1.1. 什么是Session Session一般译为会话,是解决Http协议的无状态问题的方案,可以将一次会话中的数据存储在服务器端的内存中,保证在下一次的会话中可以使用. ...

  2. iOS_KVC与KVO

    目 录: 一.KVC   二.KVO                                                                                   ...

  3. MIPI DBI\DPI\DSI简介【转】

    本文转载自:http://blog.csdn.net/longxiaowu/article/details/24249971 (1)DBI接口 A,也就是通常所讲的MCU借口,俗称80 system接 ...

  4. Oracle基本概念

    1. 数据库和实例 什么是数据库,其实很简单,数据库就是存储数据的一种媒介.比如常用的文件就是一种,在Oracle10g中,数据的存储有好几种.第一种是文件形 式,也就是在你的磁盘中创建一批文件,然后 ...

  5. 字符串问题之 去掉字符串中连续出现K个0的子串

    字符串中刚好出现K个连续的‘O’,则把K个连续‘O’字符去除,返回处理后的字符串 比如 str="AOOOOOBOOO"   k=3, 返回“AOOOOOB” 这个题的解决思路也有 ...

  6. mac下安装py第三方库到python3下

    python3 -m pip install **** 中间可能碰到超时问题 python3 pip --default-timeout=100 install -U **** 设置默认超时时间即可 ...

  7. window 下安装并启动zookeeper

    1.下载zookeeper压缩包并解压大到磁盘中: 2.进入解压文件的: 3.进入conf,修改配置文件如下: 4.启动: 启动完成:

  8. nginx流量全copy记录

    参考:http://tyrion.iteye.com/blog/2311987 准备两台服务器: 0.0.0.1 0.0.0.2 在 0.0.0.1上 . 下载 wget https://github ...

  9. poj 2478 Farey Sequence 欧拉函数前缀和

    Farey Sequence Time Limit: 1000MS   Memory Limit: 65536K       Description The Farey Sequence Fn for ...

  10. python定制

    1.简单定制   a.使用time模块的localtime方法获取时间 b.time.localtime返回struct_time的时间格式 c.表现你的类:__str__和__repr__ 注:当属 ...