一、sleep和wait的区别。

1.wait可以指定时间,也可以不指定。

而sleep必须制定。

2.在同步的时候,对于CPU的执行权和以及锁的处理不同。

wait:释放执行权,释放锁。

sleep:释放执行权,不释放锁。

二、线程是否安全?

  1. class Test implements Runnable
  2. {
  3. public synchronized void show()
  4. {
  5. try
  6. {
  7. wait();
  8. }
  9. catch (InterruptedException e)
  10. {
  11. }
  12. }
  13. public synchronized void method()
  14. {
  15. notifyAll();
  16. }
  17. }

假设有四个线程0123,其中有三个线程012全部挂在wait上了,另外一个线3程则调用了notifyAll方法,这样在同步代码块中就有了三个线程,这和“在同步代码块中只能有一个线程”的原则相违背,线程变得不安全了。这话乍听起来没有错,事实上是有问题的。实际上,当线程3调用了notifyAll方法的时候,CPU执行权还在自己手里,而被唤醒的三个线程虽然拥有了执行资格,但是仅仅是执行资格,他们将会加入堵塞队列,等待执行权;等到线程三释放了执行权以及锁(method方法结束),在堵塞队列中的012线程中的一个将会获得执行权,任务结束后,释放锁以及执行权并交给下一个线程。。

验证代码:

  1. class Test implements Runnable
  2. {
  3. public boolean flag=true;
  4. public void run()
  5. {
  6. if(this.flag==true)
  7. show();
  8. else
  9. method();
  10. }
  11. public synchronized void show()
  12. {
  13. System.out.println(Thread.currentThread().getName()+":将会等待");
  14. try
  15. {
  16. wait();
  17. }
  18. catch (InterruptedException e)
  19. {
  20. }
  21. for(int i=1;i<=10;i++)
  22. {
  23. try
  24. {
  25. Thread.sleep(50);
  26. }
  27. catch (InterruptedException e)
  28. {
  29. }
  30. System.out.println(Thread.currentThread().getName()+":正在执行"+i);
  31. }
  32. }
  33. public synchronized void method()
  34. {
  35. System.out.println(Thread.currentThread().getName()+":将会唤醒所有线程");
  36. notifyAll();
  37. for(int i=1;i<=10;i++)
  38. {
  39. try
  40. {
  41. Thread.sleep(50);
  42. }
  43. catch (InterruptedException e)
  44. {
  45. }
  46. System.out.println(Thread.currentThread().getName()+":正在执行"+i);
  47. }
  48. }
  49. }
  50. public class Demo
  51. {
  52. public static void main(String args[])
  53. {
  54. Test t=new Test();
  55. Thread t1=new Thread(t);
  56. Thread t2=new Thread(t);
  57. Thread t3=new Thread(t);
  58. Thread t4=new Thread(t);
  59. t1.start();
  60. t2.start();
  61. t3.start();
  62.  
  63. try
  64. {
  65. Thread.sleep(20);
  66. }
  67. catch (InterruptedException e)
  68. {
  69. }
  70. t.flag=false;
  71. t4.start();
  72.  
  73. }
  74. }

其运行结果和预想的结果相同。

三、怎么结束线程

1.使用stop方法:已过时,不推荐使用。

2.控制run方法结束。

可以使用标志变量的方法。

  1. /*
  2. 能控制线程停止的情况。
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. while(flag)
  10. System.out.println(Thread.currentThread().getName()+":+++++++++++++++++++");
  11. }
  12. public void setFlag()
  13. {
  14. this.flag=false;
  15. }
  16. }
  17. public class Demo
  18. {
  19. public static void main(String args[])
  20. {
  21. Test t=new Test();
  22. Thread t1=new Thread(t);
  23. Thread t2=new Thread(t);
  24. t1.start();
  25. t2.start();
  26.  
  27. int sum=0;
  28. while(true)
  29. {
  30. System.out.println(Thread.currentThread().getName()+":sum+"+"/////////////////////////////");
  31. if(++sum==20)
  32. {
  33. t.setFlag();
  34. System.out.println("over");
  35. break;
  36. }
  37. }
  38. }
  39. }

这是在未加同步的时候。若是加上同步,有的时候就不管用了。

  1. /*
  2. 不能控制线程停止的情况。
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. while(flag)
  10. {
  11. synchronized(this)
  12. {
  13. System.out.println(Thread.currentThread().getName()+"正在执行");
  14. try
  15. {
  16. this.wait();
  17. }
  18. catch(InterruptedException e)
  19. {
  20. System.out.println(Thread.currentThread().getName()+":+++++++++++++++++++");
  21. }
  22. }
  23. }
  24. }
  25. public void setFlag()
  26. {
  27. this.flag=false;
  28. }
  29. }
  30. public class Demo
  31. {
  32. public static void main(String args[])
  33. {
  34. Test t=new Test();
  35. Thread t1=new Thread(t);
  36. Thread t2=new Thread(t);
  37. t1.start();
  38. t2.start();
  39.  
  40. int sum=0;
  41. while(true)
  42. {
  43. System.out.println(Thread.currentThread().getName()+":sum+"+"/////////////////////////////");
  44. if(++sum==20)
  45. {
  46. t.setFlag();
  47. System.out.println("over");
  48. break;
  49. }
  50. }
  51. }
  52. }

由于线程0、1均进入了冻结状态,所以不再判断flag标记,线程也就不会结束了。

3.使用interrupt方法结束线程。

此方法带有强制性,因此会抛出异常,需要捕获。

interrupt方法的功能是将处于冻结状态的线程强制性唤醒,使其具有CPU执行资格。

  1. /*
  2. 使用interrupt方法控制线程停止的情况。
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. while(flag)
  10. {
  11. synchronized(this)
  12. {
  13. System.out.println(Thread.currentThread().getName()+"正在执行");
  14. try
  15. {
  16. this.wait();
  17. }
  18. catch(InterruptedException e)
  19. {
  20. System.out.println(Thread.currentThread().getName()+":+++++++++++++++++++");
  21. }
  22. }
  23. }
  24. }
  25. public void setFlag()
  26. {
  27. this.flag=false;
  28. }
  29. }
  30. public class Demo
  31. {
  32. public static void main(String args[])
  33. {
  34. Test t=new Test();
  35. Thread t1=new Thread(t);
  36. Thread t2=new Thread(t);
  37. t1.start();
  38. t2.start();
  39.  
  40. int sum=0;
  41. while(true)
  42. {
  43. System.out.println(Thread.currentThread().getName()+":sum+"+"/////////////////////////////");
  44. if(++sum==20)
  45. {
  46. t.setFlag();
  47. t1.interrupt();
  48. t2.interrupt();
  49. System.out.println("over");
  50. break;
  51. }
  52. }
  53. }
  54. }

4、使用守护线程

setDaemon方法:设置线程为守护线程或者用户线程、后台线程。

守护线程具有依附性,一旦所依附的线程结束,自己也将会消失,所以要“守护”,所以叫“用户线程”(这是和系统线程相对应的叫法)。

JAVA中规定,一旦程序中线程全部为守护线程,则JAVA虚拟机将会自动退出,所有线程都将会结束。

将t2设置成守护线程,一旦t1线程和main线程全部结束,t2线程将成为唯一一个线程而且是守护线程,JAVA虚拟机将会自动退出,t2线程也会跟着结束。

  1. /*
  2. 守护线程举例。
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. while(flag)
  10. {
  11. synchronized(this)
  12. {
  13. System.out.println(Thread.currentThread().getName()+"正在执行");
  14. try
  15. {
  16. this.wait();
  17. }
  18. catch(InterruptedException e)
  19. {
  20. System.out.println(Thread.currentThread().getName()+":+++++++++++++++++++");
  21. }
  22. }
  23. }
  24. }
  25. public void setFlag()
  26. {
  27. this.flag=false;
  28. }
  29. }
  30. public class Demo
  31. {
  32. public static void main(String args[])
  33. {
  34. Test t=new Test();
  35. Thread t1=new Thread(t);
  36. Thread t2=new Thread(t);
  37. t1.start();
  38. //要在t2线程开启之前设置。
  39. t2.setDaemon(true);
  40.  
  41. t2.start();
  42.  
  43. int sum=0;
  44. while(true)
  45. {
  46. System.out.println(Thread.currentThread().getName()+":sum+"+"/////////////////////////////");
  47. if(++sum==20)
  48. {
  49. t.setFlag();
  50. t1.interrupt();
  51. //t2.interrupt();
  52. System.out.println("over");
  53. break;
  54. }
  55. }
  56. }
  57. }

设置守护线程要在线程启动之前设置。

四.join方法。

join方法的功能:加入当前线程,当前线程会释放执行权,一直等到新加入的线程执行完任务之后才执行自己的任务。

  1. /*
  2. join方法使用
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. int sum=1;
  10. while(++sum<21)
  11. {
  12.  
  13. System.out.println(Thread.currentThread().getName()+":+++++++");
  14. }
  15. }
  16. public void setFlag()
  17. {
  18. this.flag=false;
  19. }
  20. }
  21. public class Demo
  22. {
  23. public static void main(String args[]) throws Exception
  24. {
  25. Test t=new Test();
  26. Thread t1=new Thread(t);
  27. Thread t2=new Thread(t);
  28. t1.start();
  29. t1.join();
  30.  
  31. t2.start();
  32.  
  33. int sum=0;
  34. while(true)
  35. {
  36. System.out.println(Thread.currentThread().getName()+":sum+"+"/////////////////////////////");
  37. if(++sum==20)
  38. {
  39. t.setFlag();
  40. t1.interrupt();
  41. t2.interrupt();
  42. System.out.println("over");
  43. break;
  44. }
  45. }
  46. }
  47. }

五、线程优先级

toString方法:返回字符串包括线程名称、线程优先级、线程所属的线程组。

线程有10个优先级1-10,且数字越大,优先级越大。为了便于使用,将优先级划分为三级:

Thread.MAX_PRIORITY:最大优先级,相当于10

Thread.MIN_PRIORITY:最小优先级,相当于1

Thread.MAX_PRIORITY:默认优先级,相当于5

设置优先级的方法是setPriority();

  1. /*
  2. 验证优先级,其实没什么效果
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. int sum=1;
  10. while(++sum<21)
  11. {
  12.  
  13. System.out.println(Thread.currentThread());
  14. }
  15. }
  16. public void setFlag()
  17. {
  18. this.flag=false;
  19. }
  20. }
  21. public class Demo
  22. {
  23. public static void main(String args[]) throws Exception
  24. {
  25. Test t=new Test();
  26. Thread t1=new Thread(t);
  27. Thread t2=new Thread(t);
  28.  
  29. t1.setPriority(Thread.MAX_PRIORITY);
  30. Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  31. t2.setPriority(Thread.NORM_PRIORITY);
  32.  
  33. t1.start();
  34. t2.start();
  35.  
  36. int sum=0;
  37. while(true)
  38. {
  39. System.out.println(Thread.currentThread());
  40. if(++sum==20)
  41. {
  42. t.setFlag();
  43. t1.interrupt();
  44. t2.interrupt();
  45. System.out.println("over");
  46. break;
  47. }
  48. }
  49. }
  50. }

应当注意的是,设置优先级的高低只是增加或者减小CPU切换到的概率,实际上仍然要争夺CPU执行权。

六、yied方法

yield方法是静态方法,使用Thread类名直接调用,作用是释放当前线程的执行权。给别的线程更多的机会执行任务。

  1. /*
  2. 验证yield方法,是Thread类的静态方法。
  3. */
  4. class Test implements Runnable
  5. {
  6. private boolean flag=true;
  7. public void run()
  8. {
  9. int sum=1;
  10. while(sum<20)
  11. {
  12. try
  13. {
  14. Thread.sleep(10);
  15. }
  16. catch(InterruptedException e){}
  17. System.out.println(Thread.currentThread()+":"+sum);
  18. Thread.yield();
  19. sum++;
  20. }
  21. }
  22. public void setFlag()
  23. {
  24. this.flag=false;
  25. }
  26. }
  27. public class Demo
  28. {
  29. public static void main(String args[])
  30. {
  31. Test t=new Test();
  32. Thread t1=new Thread(t);
  33. Thread t2=new Thread(t);
  34. t1.start();
  35. t2.start();
  36.  
  37. }
  38. }

我们可以观察到两个线程任务的执行进度高度同步,这是由于yied方法强制放弃CPU执行权造成的。

【JAVA多线程中使用的方法】的更多相关文章

  1. java 多线程中的wait方法的详解

    java多线程中的实现方式存在两种: 方式一:使用继承方式 例如: PersonTest extends Thread{ String name; public PersonTest(String n ...

  2. Java多线程中的join()方法

    一.join()方法介绍 join() 定义在Thread.java中.join()方法把指定的线程加入到当前线程,可以将两个交替执行的线程合并为顺序执行的线程.比如在线程B中调用了线程A的join( ...

  3. 浅谈Java多线程中的join方法

    先上代码 新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String ...

  4. Java多线程中的join方法

    新建一个Thread,代码如下: package com.thread.test; public class MyThread extends Thread { private String name ...

  5. java多线程中关于join方法的使用

    Thread的非静态方法join()让一个线程B"加入"到另外一个线程A的尾部.在A执行完毕之前,B不能工作.例如:         Thread t = new MyThread ...

  6. Java并发编程--多线程中的join方法详解

    Java Thread中, join()方法主要是让调用该方法的thread在完成run方法里面的部分后, 再执行join()方法后面的代码 例如:定义一个People类,run方法是输出姓名年龄. ...

  7. java多线程中的三种特性

    java多线程中的三种特性 原子性(Atomicity) 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并 ...

  8. Java多线程中的常用方法

    本文将带你讲诉Java多线程中的常用方法   Java多线程中的常用方法有如下几个 start,run,sleep,wait,notify,notifyAll,join,isAlive,current ...

  9. Java多线程中的竞争条件、锁以及同步的概念

    竞争条件 1.竞争条件: 在java多线程中,当两个或以上的线程对同一个数据进行操作的时候,可能会产生“竞争条件”的现象.这种现象产生的根本原因是因为多个线程在对同一个数据进行操作,此时对该数据的操作 ...

随机推荐

  1. 顺序栈的c++实现及利用其实现括号的匹配

    #include<iostream>#include<cassert>#include<cstring>#include<string>using na ...

  2. (转载)XML解析之-XStream解析

    转载来源:http://hwy584624785.iteye.com/blog/1168680 本例使用XStream生成一个xml文件,再发序列化xml文件内容. XStream是一个简单的类库,可 ...

  3. 模式串匹配,kmp

    #include <stdio.h> #include <stdlib.h> #include <string> #include<string.h> ...

  4. 11.7---叠罗汉表演节目(CC150)

    1,牛客网第一题:这其实跟找最长递增子序列是一个东西.注意的地方是,返回的是最大的dp,而不是dp[N-1]. 答案: public static int getHeight(int[] men, i ...

  5. VS2012创建UML项目

    1.选择建模工具 2.添加新建项 3.添加UML图或用例图 4.打开工具箱添加

  6. [k]web页面-browser兼容问题-1

    1:空的a标签在IE7/8下不能点击(2015-05-22) html代码: <ul class='oUl'><li><a href="#"> ...

  7. pip安装简单方法

    前提:有网络 wget -c --no-check-certificate https://bootstrap.pypa.io/get-pip.py python get-pip.py

  8. struts2框架 初始别

    struts2 是webwork和struts合并而来. 1.下载struts2 说明: Full Distribution: 为完整版下载,建议下载它 Example Applications:st ...

  9. Robot Framework + Selenium2Library环境下,结合Selenium Grid实施分布式自动化测试

    最近一段时间,公司在推行自动化测试流程,本人有幸参与了自定义通用控件的关键字封装和脚本辅助编写.数据驱动管理.测试用例执行管理等一系列工具软件的研发工作,积累了一些经验,在此与大家做一下分享,也算是做 ...

  10. spring + myBatis 常见错误:SQL语法错误

    在程序运行时,有时候会出现如下错误: 这个错误通常是你的sqlmapper.xml中sql语句语法有错误.所以请仔细查看你sql语句是否正确,比如{#id}这样写就会报上述错误,其实应该#{id}这样 ...