不知道怎么回事,先写在word文档上的,但是保存后变的很乱。。

1.锁对象的方法:wait(),notify(),notifyAll()

2.线程的方法:

join(),interrupt(),sleep() ,其中stop(),suspend()由于不安全,已经建议不再使用

3.Wait()方法

释放锁并让自己一直处于等待状态。

看下面的例子:

/**
  * Created by
  * Date : 2018/7/9 14:46
  */
 public class Main {

     private final Object flag=new Object();

     public static void main(String[] args){
         Main m=new Main();
         m.test();
     }

     public void test(){
         new Thread(){
             public void run(){
                 System.out.println("执行线程");
                 try{
                     flag.wait();
                 }catch (InterruptedException e){
                     e.printStackTrace();
                 }
                 System.out.println("结束线程");
             }
         }.start();
     }
 }

执行的结果:

执行线程

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
         at java.lang.Object.wait(Native Method)
         at java.lang.Object.wait(Object.java:503)
         at threadTest.wait.Main$1.run(Main.java:21)

这儿报异常了。是因为调用wait()方法必须是要锁的对象调用,我们修改如下:

/**

 * Created by 

 * Date : 2018/7/9 14:46

 */

public class Main {



    private final Object flag=new Object();



    public static void main(String[] args){

        Main m=new Main();

        m.test();

    }



    public void test(){

        new Thread(){

            public void run(){

                synchronized(flag){

                    System.out.println("执行线程");

                    try{

                        flag.wait();

                    }catch (InterruptedException e){

                        e.printStackTrace();

                    }

                    System.out.println("结束线程");

                }

            }

        }.start();

    }

}

执行结果:

执行线程

调用wait()方法后,上述代码就会一直等待中,直到调用notify()或者notifyAll()等方法通知正在等待的线程获取锁继续执行。

4.Notify()与notifyAll()方法

要想理解这个方法,我们先要理解两个概念:

  1. 锁池:有多个线程在竞争锁,其中一个线程A竞争到了锁,那么其它的线程就会进入锁池中,等待线程A释放锁,再次竞争
  2. 等待池:当线程调用了对象的wait()方法后,该线程就会进入等待池,等待池中的线程不会去竞争锁

当调用notify()方法时,会随机将等待池中的该对象的一个线程移到锁池中再次竞争,当调用notifyAll()方法时,会将等待池中的所有的该对象的线程移到锁池中再次竞争。

看下面的例子:

/**

 * Created by 

 * Date : 2018/7/9 14:46

 */

public class Main {



    private final Object flag=new Object();



    public static void main(String[] args)throws InterruptedException{

        Main m=new Main();

        m.test();

        TimeUnit.SECONDS.sleep(2);



        System.out.println("notify thread");



        //通知

        m.testNotify();

    }



    public void test(){

        for(int i=1;i<=5;i++){

            new Thread(String.valueOf(i)){

                public void run(){

                    synchronized(flag){

                        System.out.println("线程"+Thread.currentThread().getName()+"执行线程");

                        try{

                            flag.wait();

                        }catch (InterruptedException e){

                            e.printStackTrace();

                        }

                        System.out.println("线程"+Thread.currentThread().getName()+"结束线程");

                    }

                }

            }.start();

        }

    }



    public void testNotify(){

        synchronized (flag){

            flag.notify();

        }

    }

}

执行结果:

线程2执行线程
线程1执行线程
线程3执行线程
线程5执行线程
线程4执行线程
notify thread
线程2结束线程

同样的,在调用notify()方法时也需要同步对象,它会随机通知一个线程。

如果将程序中的flag.notify()改为flag.notifyAll(),则执行结果为:

线程4执行线程
线程1执行线程
线程5执行线程
线程3执行线程
线程2执行线程
notify thread
线程2结束线程
线程3结束线程
线程5结束线程
线程1结束线程
线程4结束线程

5.Sleep()方法

不释放锁,中断一段时间之后继续执行。

看下面的例子:

/**

 * Created by WangZhiXin

 * Date : 2018/7/9 14:46

 */

public class Main {



    private final Object flag=new Object();



    public static void main(String[] args){

        Main m=new Main();

        m.test();

    }



    public void test(){

        new Thread(){

            public void run(){

                System.out.println("执行线程");

                try{

                    Thread.sleep(3000);

                }catch (InterruptedException e){

                    e.printStackTrace();

                }

                System.out.println("结束线程");

            }

        }.start();

    }

}

执行的结果:

执行线程
结束线程

当隔了三秒后,程序会继续执行,在此期间不释放锁。

6.Join()方法

可以让线程同步执行。当线程A执行start()后,再执行线程A的join(),可以让其它线程等待直到线程A执行结束。其实它的原理就是用wait()方法,有兴趣的小伙伴可以研究下源码。

看下面的例子:

/**

 * Created by 

 * Date : 2018/7/9 15:35

 */

public class Main {



    public static void main(String[] args)throws InterruptedException{

        for(int i=1;i<=10;i++){

            Thread th=new Thread(String.valueOf(i)){

                public void run(){

                    System.out.println("线程"+Thread.currentThread().getName()+"执行线程");

                }

            };

            th.start();

            th.join();

        }

    }

}

执行结果:

线程1执行线程
线程2执行线程
线程3执行线程
线程4执行线程
线程5执行线程
线程6执行线程
线程7执行线程
线程8执行线程
线程9执行线程
线程10执行线程

如果th.join()在th.start()之前执行,那么也不会达到同步的效果

7.Interrupt()

Interrupt()方法主要用来改变线程的运行状态。当线程处于“阻塞状态”时,调用interrupt()会抛出interruptException异常;当线程处于“运行状态”时,调用interrupt()不会抛出异常,但调用isInterrupted()方法会返回true。

举例如下:

/**
  * Created by
  * Date : 2018/7/9 18:39
  */
 public class Main {

     public static void main(String[] args)throws InterruptedException{
         Main m=new Main();
         Thread aTh=m.running();
         Thread oTh=m.over();

         TimeUnit.SECONDS.sleep(1);
         aTh.interrupt();
         oTh.interrupt();
     }

     public Thread running(){
         Thread aTh=new Thread("A"){
             public void run(){
                 while(!Thread.currentThread().isInterrupted()){
                     System.out.println(Thread.currentThread().getName()+"线程状态未改变");
                 }
                 System.out.println(Thread.currentThread().getName()+"线程状态已改变");
             }
         };
         aTh.start();
         return aTh;
     }

     public Thread over(){
         Thread oTh=new Thread("B"){
             public void run(){
                 try{
                     TimeUnit.SECONDS.sleep(100000000);
                 }catch (InterruptedException e){
                     System.out.println(Thread.currentThread().getName()+"线程阻塞,调用interrupt()方法,直接抛异常");
                 }
             }
         };
         oTh.start();
         return oTh;
     }
 }运行结果:
A线程状态未改变
A线程状态未改变
A线程状态未改变
A线程状态已改变

B线程阻塞,调用interrupt()方法,直接抛异常

通过以上可以看出,B线程被阻塞了,所以可以被中断,并抛出了异常;A线程一直在运行,调用interrupt(),却没抛出异常,仅仅是线程的状态改变了,这儿的A线程其实也可以用boolean变量来代替使用。

综上所述,标准的线程阻塞写法是:

try {
     // 1. isInterrupted()保证,只要中断标记为true就终止线程。
     while (!Thread.currentThread().isInterrupted()) {
         // 执行任务...
     }
 } catch (InterruptedException ie) {
     // 2. InterruptedException异常保证,当InterruptedException异常产生时,线程被终止。
 }