zoukankan      html  css  js  c++  java
  • java Thread源码分析(二)

    一、sleep的使用

     1 public class ThreadTest {
     2     public static void main(String[] args) throws InterruptedException {
     3         Object obj = new Object();
     4         MyThread mt = new MyThread(obj);
     5         mt.start();
     6         MyThread mt2 = new MyThread(obj);
     7         mt2.start();
     8     }
     9     private static class MyThread extends Thread{
    10         private Object obj;
    11         public MyThread(Object obj) {
    12             this.obj = obj;
    13         }
    14         @Override
    15         public void run() {
    16             System.out.println(Thread.currentThread().getName() + 
    17                     " synchronized之前: " + System.currentTimeMillis());
    18             synchronized(obj) {
    19                 System.out.println(Thread.currentThread().getName() + 
    20                         " sleep之前: " + System.currentTimeMillis());
    21                 try {
    22                     Thread.sleep(2000);
    23                 } catch (InterruptedException e) {
    24                     e.printStackTrace();
    25                 }
    26                 System.out.println(Thread.currentThread().getName() + 
    27                         " sleep之后: " + System.currentTimeMillis());
    28             }
    29         }
    30     }
    31 }
    View Code

    输出:

    Thread-1 synchronized之前: 1546337474050
    Thread-0 synchronized之前: 1546337474050
    Thread-1 sleep之前: 1546337474051
    Thread-1 sleep之后: 1546337476051
    Thread-0 sleep之前: 1546337476051
    Thread-0 sleep之后: 1546337478052

    线程Thread-0和线程Thread-1监控同一个资源obj,Thread-1在sleep之后并没有释放对象锁。

    好比,A和B去店里买衣服,只有一间试衣间,一把试衣间的钥匙,A先拿到试衣间钥匙(obj),进入试衣间(synchronized(obj) {...}),

    并在试衣间睡了一觉(sleep(2000)),B只能等A醒来走出试衣间,才能有机会拿到钥匙并进入试衣间。

    调用native方法:public static native void sleep(long millis) throws InterruptedException;

    二、wait和notify的使用

     1 public class ThreadTest {
     2     public static void main(String[] args) throws InterruptedException {
     3         Object obj = new Object();
     4         MyThread mt = new MyThread(obj);
     5         mt.start();
     6         MyThread2 mt2 = new MyThread2(obj);
     7         mt2.start();
     8     }
     9     private static class MyThread extends Thread{
    10         private Object obj;
    11         public MyThread(Object obj) {
    12             this.obj = obj;
    13         }
    14         @Override
    15         public void run() {
    16             System.out.println(Thread.currentThread().getName() + 
    17                     " synchronized之前: " + System.currentTimeMillis());
    18             synchronized(obj) {
    19                 System.out.println(Thread.currentThread().getName() + 
    20                         " wait之前: " + System.currentTimeMillis());
    21                 try {
    22                     obj.wait();
    23                 } catch (InterruptedException e) {
    24                     // TODO Auto-generated catch block
    25                     e.printStackTrace();
    26                 }
    27                 System.out.println(Thread.currentThread().getName() + 
    28                         " wait之后: " + System.currentTimeMillis());
    29             }
    30         }
    31     }
    32     private static class MyThread2 extends Thread{
    33         private Object obj;
    34         public MyThread2(Object obj) {
    35             this.obj = obj;
    36         }
    37         @Override
    38         public void run() {
    39             System.out.println(Thread.currentThread().getName() + 
    40                     " synchronized之前: " + System.currentTimeMillis());
    41             synchronized(obj) {
    42                 System.out.println(Thread.currentThread().getName() + 
    43                         " notify之前: " + System.currentTimeMillis());
    44                 obj.notify();
    45                 System.out.println(Thread.currentThread().getName() + 
    46                         " notify之后: " + System.currentTimeMillis());
    47             }
    48         }
    49     }
    50 }
    View Code

    输出:

    Thread-0 synchronized之前: 1546349737274
    Thread-0 wait之前: 1546349737274
    Thread-1 synchronized之前: 1546349737274
    Thread-1 notify之前: 1546349737275
    Thread-1 notify之后: 1546349737275
    Thread-0 wait之后: 1546349737275

    Thread-0在执行了obj.wait()之后,线程暂停并释放对象锁,之后,Thread-1获得对象锁,Thread-1执行obj.notify()后Thread-0苏醒,Thread-1执行完synchronized的代码块之后,Thread-0才有机会获得锁。

    1、wait()让当前线程进入“等待状态”,并让当前线程释放它所持有的锁。直到其他线程调用此对象的notify()方法或notify()方法,当前线程被唤醒,进入“就绪状态”。

    2、notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程。notify()是唤醒单个线程(随机唤醒),而notifyAll()是唤醒所有的线程。

    3、wait(long timeout)让当前线程处于“等待(阻塞)状态”,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量,当前线程被唤醒,进入“就绪状态”。

    4、调用 wait()、notify()、notifyAll() 方法之前,必须获得对象锁,即,只能在同步方法中调用。

    5、执行 notify() 之后,并不会立即退出让wait的线程执行,必须要先将同步块中的程序执行完,退出同步块,才会释放锁,让等待线程执行。

    6、每调用一次 notify() 只能唤醒一个线程,多次调用可通知多个线程。

    wait()、notify()、notifyAll()都是Object的方法。

    原理:

    每个对象都有个monitor,初始是0,执行完synchronized值就是1。

    wait/notify需要在获得monitor的线程中才可以执行。

    所以,wait/notify需要在synchronized中执行。

    其中,wait又会释放掉锁,破坏掉同步。

    和synchronized的关系:

    synchronized代码块生成的字节码,被monitorenter和monitorexit包围,持有对象的monitor,线程执行wait/notify方法时,必须持有对象的monitor,所以,wait/notify方法在synchronized同步快中执行,就持有了对象的锁。

    互斥和协同:

    java语言的同步机制在底层实现上就只有两种方式:互斥和协同。

    互斥:即synchronized内置锁。

    协同:即内置条件队列,wait/notify/notyfiAll。

    条件队列是处于等待状态的线程,等待特定条件为真。每个java对象都可以作为一个锁,同样每个java对象都可以作为一个条件队列。通过wait/notify/notifyAll来操作条件队列。

    可以理解为:有一个队列,o.wait()就push进去,o.notify()就pull出来。、

    要调用条件队列的任何一个方法,都必须要获得对象上的锁。

    三、join的使用

     1 public class ThreadTest {
     2     public static void main(String[] args) throws InterruptedException {
     3         Object obj = new Object();
     4         MyThread mt = new MyThread(obj);
     5         mt.start();
     6         //在main中调用mt.join()
     7         mt.join();    
     8         System.out.println("main");
     9     }
    10     private static class MyThread extends Thread{
    11         private Object obj;
    12         public MyThread(Object obj) {
    13             this.obj = obj;
    14         }
    15         @Override
    16         public void run() {
    17             System.out.println(Thread.currentThread().getName() + 
    18                     " synchronized之前: " + System.currentTimeMillis());
    19             synchronized(obj) {
    20                 System.out.println(Thread.currentThread().getName() + 
    21                         " sleep之前: " + System.currentTimeMillis());
    22                 try {
    23                     Thread.sleep(3000);
    24                 } catch (InterruptedException e) {
    25                     // TODO Auto-generated catch block
    26                     e.printStackTrace();
    27                 }
    28                 System.out.println(Thread.currentThread().getName() + 
    29                         " sleep之后: " + System.currentTimeMillis());
    30             }
    31         }
    32     }
    33 }
    View Code

    输出:

    Thread-0 synchronized之前: 1546354871560
    Thread-0 sleep之前: 1546354871560
    Thread-0 sleep之后: 1546354874561
    main

    在main中调用了线程mt的join方法(mt.join()),则线程main会等线程mt执行完毕后再恢复运行。

    join()方法由wait()实现。源码:

  • 相关阅读:
    Linux 命令查找文件中某个字段所存在的位置
    PHP in_array() 函数
    php一维数组如何追加到二维数组
    电脑切换窗口
    微擎前端逻辑判断的时弹框
    JDBC批量处理
    数据库事务
    处理BLOB
    JDBC自动生成主键值
    JDBC的元数据
  • 原文地址:https://www.cnblogs.com/natian-ws/p/10211321.html
Copyright © 2011-2022 走看看