一段多线程锁机制的代码,看完你会提高不少。

来源:互联网 发布:网络剧 有毒 第一季 编辑:程序博客网 时间:2024/05/17 22:28

最近看到一段很有意思的代码,先贴出来。

/**      *       *      sleep(); 休眠,不会丢失任何监视器的所有权      *       wait(); 等待,释放对监视器的所有权       *     notice(); Wakes up a single thread that is waiting on this object's monitor      *  notifyAll(); Wakes up all threads that are waiting on this object's monitor.      *  synchronized: 加锁同步,实际上就是并行执行串行化      * @author Administrator      *      */      public class Test {          public static void main(String[] args) {              MyClass1 myClass = new MyClass1();              new MyThread(myClass).start();              new MyThread1(myClass).start();          }      }      class MyClass1 {          public synchronized void m1() {              System.out.println("m1-1");              try {               // wait():当前线程等待,直到另一个线程调用notify()或者notifyAll();              // 执行wait()方法后释放对监视器(myClass.m1())的所有权,也就是释放锁                  this.wait(); // 暂停改当前线程,并且会释放锁              } catch (Exception e) {                  e.printStackTrace();              }              System.out.println("m1-2");              try {                  Thread.sleep(1000); // m1和m2同时暂停1秒钟                  System.out.println("m1-3");              } catch (InterruptedException e) {                  e.printStackTrace();              }              System.out.println("m1-4");              m2();          }          public synchronized void m2() {              System.out.println("m2-1");              // 唤醒m1,但是并不释放锁synchronized          // Wakes up all threads that are waiting on this object's monitor               this.notifyAll();            System.out.println("m2-2");              try {               // 当前正在执行的线程休眠,线程不丢失任何监视器的所有权,也就是不会释放锁                  Thread.sleep(1000);                  System.out.println("m2-3");              } catch (InterruptedException e) {                  e.printStackTrace();              }              System.out.println("m2-4");              m1();          }      }      class MyThread extends Thread {          private MyClass1 myClass;          public MyThread(MyClass1 myClass){              this.myClass = myClass;          }          @Override          public void run() {              myClass.m1();          }      }      class MyThread1 extends Thread {          private MyClass1 myClass;          public MyThread1(MyClass1 myClass){              this.myClass = myClass;          }          @Override          public void run() {              try { // 暂停10毫秒是为了让m1先执行wait                  Thread.sleep(10);              } catch (InterruptedException e1) {                  e1.printStackTrace();              }              myClass.m2();          }      }  

线程基础不好的相信已经看晕了,没关系,实践是检验真理的唯一标准,下面我们看在JDK1.6下面的运行结果:

[test] 2011-03-19 09:25:25 [Thread-0] :m1-1[test] 2011-03-19 09:25:25 [Thread-1] :m2-1[test] 2011-03-19 09:25:25 [Thread-1] :m2-2[test] 2011-03-19 09:25:26 [Thread-1] :m2-3[test] 2011-03-19 09:25:26 [Thread-1] :m2-4[test] 2011-03-19 09:25:26 [Thread-1] :m1-1[test] 2011-03-19 09:25:26 [Thread-0] :m1-2[test] 2011-03-19 09:25:27 [Thread-0] :m1-3[test] 2011-03-19 09:25:27 [Thread-0] :m1-4[test] 2011-03-19 09:25:27 [Thread-0] :m2-1[test] 2011-03-19 09:25:27 [Thread-0] :m2-2[test] 2011-03-19 09:25:28 [Thread-0] :m2-3[test] 2011-03-19 09:25:28 [Thread-0] :m2-4[test] 2011-03-19 09:25:28 [Thread-0] :m1-1[test] 2011-03-19 09:25:28 [Thread-1] :m1-2[test] 2011-03-19 09:25:29 [Thread-1] :m1-3[test] 2011-03-19 09:25:29 [Thread-1] :m1-4[test] 2011-03-19 09:25:29 [Thread-1] :m2-1[test] 2011-03-19 09:25:29 [Thread-1] :m2-2[test] 2011-03-19 09:25:30 [Thread-1] :m2-3[test] 2011-03-19 09:25:30 [Thread-1] :m2-4[test] 2011-03-19 09:25:30 [Thread-1] :m1-1[test] 2011-03-19 09:25:30 [Thread-0] :m1-2[test] 2011-03-19 09:25:31 [Thread-0] :m1-3[test] 2011-03-19 09:25:31 [Thread-0] :m1-4[test] 2011-03-19 09:25:31 [Thread-0] :m2-1[test] 2011-03-19 09:25:31 [Thread-0] :m2-2[test] 2011-03-19 09:25:32 [Thread-0] :m2-3[test] 2011-03-19 09:25:32 [Thread-0] :m2-4[test] 2011-03-19 09:25:32 [Thread-0] :m1-1[test] 2011-03-19 09:25:32 [Thread-1] :m1-2[test] 2011-03-19 09:25:33 [Thread-1] :m1-3[test] 2011-03-19 09:25:33 [Thread-1] :m1-4[test] 2011-03-19 09:25:33 [Thread-1] :m2-1[test] 2011-03-19 09:25:33 [Thread-1] :m2-2[test] 2011-03-19 09:25:34 [Thread-1] :m2-3[test] 2011-03-19 09:25:34 [Thread-1] :m2-4[test] 2011-03-19 09:25:34 [Thread-1] :m1-1[test] 2011-03-19 09:25:34 [Thread-0] :m1-2[test] 2011-03-19 09:25:35 [Thread-0] :m1-3[test] 2011-03-19 09:25:35 [Thread-0] :m1-4[test] 2011-03-19 09:25:35 [Thread-0] :m2-1[test] 2011-03-19 09:25:35 [Thread-0] :m2-2[test] 2011-03-19 09:25:36 [Thread-0] :m2-3[test] 2011-03-19 09:25:36 [Thread-0] :m2-4[test] 2011-03-19 09:25:36 [Thread-0] :m1-1[test] 2011-03-19 09:25:36 [Thread-1] :m1-2[test] 2011-03-19 09:25:37 [Thread-1] :m1-3[test] 2011-03-19 09:25:37 [Thread-1] :m1-4[test] 2011-03-19 09:25:37 [Thread-1] :m2-1[test] 2011-03-19 09:25:37 [Thread-1] :m2-2[test] 2011-03-19 09:25:38 [Thread-1] :m2-3[test] 2011-03-19 09:25:38 [Thread-1] :m2-4[test] 2011-03-19 09:25:38 [Thread-1] :m1-1[test] 2011-03-19 09:25:38 [Thread-0] :m1-2[test] 2011-03-19 09:25:39 [Thread-0] :m1-3[test] 2011-03-19 09:25:39 [Thread-0] :m1-4[test] 2011-03-19 09:25:39 [Thread-0] :m2-1[test] 2011-03-19 09:25:39 [Thread-0] :m2-2[test] 2011-03-19 09:25:40 [Thread-0] :m2-3[test] 2011-03-19 09:25:40 [Thread-0] :m2-4[test] 2011-03-19 09:25:40 [Thread-0] :m1-1[test] 2011-03-19 09:25:40 [Thread-1] :m1-2 

下面开始分析我们的代码:

  1. 首先Thread-0是我们的MyThread线程,Thread-1是MyThread1线程。
  2. 程序启动Thread-0,m1方法被调用打印m1-1
  3. wait方法使线程对象放弃对象锁,等待被唤醒Thread-0线程被挂起,等待其它线程唤醒,Thread-1线程执行,m2 方法被调用;
  4. 打印m2-1,notifyAll()唤醒所有的线程,Thread-0被唤醒,但notifyall()不放开对象锁,Thread-1继续执行,打印m2-2;
  5. sleep方法使当前线程停止执行,放弃cpu时间片,让其他线程执行,但sleep方法不会使当前线程放弃锁,故m2 挂起, 1秒过后,打印m2-3,m2-4;
  6. 由于m2 持有MyClass1的锁,m2中的m1 方法可以继续执行,打印m1-1,但是由于没有释放锁,此时的线程还是在Thread-1中;
  7. 之后Thread-1遇到wait 方法使线程放弃对象锁,等待被唤醒,Thread-1被挂起,由于m2中的notifyall()已经唤醒Thread-0,所以Thread-0 开始继续执行,打印m1-2;
  8. 之后sleep方法使线程Thread-0 挂起,但不会放弃对象锁,1秒过后,继续打印m1-3,m1-4;
  9. 之后继续调用m2方法,注意此时线程仍是Thread-0,依次打印m2-1,不释放锁线程不变继续打印m2-2,m2-3,m2-4,调用m1方法,打印m1-1,这时遇到wait()Thread-0被挂起,Thread-1执行,紧接上次Thread-1停止的地方m1-1之后,打印m1-2。注意是Thread-1线程下。
  10. 重复以上过程,直至线程StackOverflowError退出。

多线程学习之路:站在大牛的肩膀上

http://blog.csdn.net/fenglibing/article/details/6278883 多线程各个方法介绍。

http://blog.psjay.com/posts/summary-of-java-concurrency-one-thread-fundation/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io Java并发总结(一):线程基础

http://blog.psjay.com/posts/summary-of-java-concurrency-two-synchronized-and-atomicity/ Java并发总结(二):同步与原子性

http://blog.psjay.com/posts/summary-of-java-concurrency-three-interrupt/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io Java并发总结(三):中断线程

http://blog.psjay.com/posts/summary-of-java-concurrency-four-collaboration/ Java并发总结(四):线程的协作

0 0
原创粉丝点击