当前位置:   article > 正文

java线程API_java 线程 api

java 线程 api

守护线程

守护线程也称为:后台线程

  • 守护线程是通过普通线程调用setDaemon(boolean on)方法设置而来的,因此创建上与普通线程无 异.
  • 守护线程的结束时机上有一点与普通线程不同,即:进程的结束.
  • 进程结束:当一个进程中的所有普通线程都结束时,进程就会结束,此时会杀掉所有正在运行的守护线 程.
  1. /**
  2. * 守护线程
  3. * 守护线程是通过普通线程调用setDaemon(true)设置而转变的。因此守护线程创建上
  4. * 与普通线程无异。
  5. * 但是结束时机上有一点不同:进程结束。
  6. * 当一个java进程中的所有普通线程都结束时,该进程就会结束,此时会强制杀死所有正在
  7. * 运行的守护线程。
  8. */
  9. public class DaemonThreadDemo {
  10. public static void main(String[] args) {
  11. Thread rose = new Thread(){
  12. public void run(){
  13. for(int i=0;i<5;i++){
  14. System.out.println("rose:let me go!");
  15. try {
  16. Thread.sleep(1000);
  17. } catch (InterruptedException e) {
  18. }
  19. }
  20. System.out.println("rose:啊啊啊啊啊啊AAAAAAAaaaaa....");
  21. System.out.println("噗通");
  22. }
  23. };
  24. Thread jack = new Thread(){
  25. public void run(){
  26. while(true){
  27. System.out.println("jack:you jump!i jump!");
  28. try {
  29. Thread.sleep(1000);
  30. } catch (InterruptedException e) {
  31. }
  32. }
  33. }
  34. };
  35. rose.start();
  36. jack.setDaemon(true);//设置守护线程必须在线程启动前进行
  37. jack.start();
  38. }
  39. }

通常当我们不关心某个线程的任务什么时候停下来,它可以一直运行,但是程序主要的工作都结束时它应当 跟着结束时,这样的任务就适合放在守护线程上执行.比如GC就是在守护线程上运行的.

多线程并发安全问题

当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致操作临界资源的顺序出现混乱严重时可能导 致系统瘫痪.

临界资源:操作该资源的全过程同时只能被单个线程完成.

  1. /**
  2. * 多线程并发安全问题
  3. * 当多个线程并发操作同一临界资源,由于线程切换的时机不确定,导致操作顺序出现
  4. * 混乱,严重时可能导致系统瘫痪。
  5. * 临界资源:同时只能被单一线程访问操作过程的资源。
  6. */
  7. public class SyncDemo {
  8. public static void main(String[] args) {
  9. Table table = new Table();
  10. Thread t1 = new Thread(){
  11. public void run(){
  12. while(true){
  13. int bean = table.getBean();
  14. Thread.yield();
  15. System.out.println(getName()+":"+bean);
  16. }
  17. }
  18. };
  19. Thread t2 = new Thread(){
  20. public void run(){
  21. while(true){
  22. int bean = table.getBean();
  23. /*
  24. static void yield()
  25. 线程提供的这个静态方法作用是让执行该方法的线程
  26. 主动放弃本次时间片。
  27. 这里使用它的目的是模拟执行到这里CPU没有时间了,发生
  28. 线程切换,来看并发安全问题的产生。
  29. */
  30. Thread.yield();
  31. System.out.println(getName()+":"+bean);
  32. }
  33. }
  34. };
  35. t1.start();
  36. t2.start();
  37. }
  38. }
  39. class Table{
  40. private int beans = 20;//桌子上有20个豆子
  41. public int getBean(){
  42. if(beans==0){
  43. throw new RuntimeException("没有豆子了!");
  44. }
  45. Thread.yield();
  46. return beans--;
  47. }
  48. }

synchronized关键字

synchronized有两种使用方式

  • 在方法上修饰,此时该方法变为一个同步方法
  • 同步块,可以更准确的锁定需要排队的代码片段

同步方法

当一个方法使用synchronized修饰后,这个方法称为"同步方法",即:多个线程不能同时 在方法内部执行.只 能有先后顺序的一个一个进行. 将并发操作同一临界资源的过程改为同步执行就可以有效的解决并发安全 问题.

  1. /**
  2. * 多线程并发安全问题
  3. * 当多个线程并发操作同一临界资源,由于线程切换的时机不确定,导致操作顺序出现
  4. * 混乱,严重时可能导致系统瘫痪。
  5. * 临界资源:同时只能被单一线程访问操作过程的资源。
  6. */
  7. public class SyncDemo {
  8. public static void main(String[] args) {
  9. Table table = new Table();
  10. Thread t1 = new Thread(){
  11. public void run(){
  12. while(true){
  13. int bean = table.getBean();
  14. Thread.yield();
  15. System.out.println(getName()+":"+bean);
  16. }
  17. }
  18. };
  19. Thread t2 = new Thread(){
  20. public void run(){
  21. while(true){
  22. int bean = table.getBean();
  23. /*
  24. static void yield()
  25. 线程提供的这个静态方法作用是让执行该方法的线程
  26. 主动放弃本次时间片。
  27. 这里使用它的目的是模拟执行到这里CPU没有时间了,发生
  28. 线程切换,来看并发安全问题的产生。
  29. */
  30. Thread.yield();
  31. System.out.println(getName()+":"+bean);
  32. }
  33. }
  34. };
  35. t1.start();
  36. t2.start();
  37. }
  38. }
  39. class Table{
  40. private int beans = 20;//桌子上有20个豆子
  41. /**
  42. * 当一个方法使用synchronized修饰后,这个方法称为同步方法,多个线程不能
  43. * 同时执行该方法。
  44. * 将多个线程并发操作临界资源的过程改为同步操作就可以有效的解决多线程并发
  45. * 安全问题。
  46. * 相当于让多个线程从原来的抢着操作改为排队操作。
  47. */
  48. public synchronized int getBean(){
  49. if(beans==0){
  50. throw new RuntimeException("没有豆子了!");
  51. }
  52. Thread.yield();
  53. return beans--;
  54. }
  55. }

同步块

有效的缩小同步范围可以在保证并发安全的前提下尽可能的提高并发效率.同步块可以更准确的控制需要 多个线程排队执行的代码片段.

语法:

  1. synchronized(同步监视器对象){
  2. 需要多线程同步执行的代码片段
  3. }

同步监视器对象即上锁的对象,要想保证同步块中的代码被多个线程同步运行,则要求多个线程看到的同步 监视器对象是同一个.

  1. /**
  2. * 有效的缩小同步范围可以在保证并发安全的前提下尽可能提高并发效率。
  3. *
  4. * 同步块
  5. * 语法:
  6. * synchronized(同步监视器对象){
  7. * 需要多个线程同步执行的代码片段
  8. * }
  9. * 同步块可以更准确的锁定需要多个线程同步执行的代码片段来有效缩小排队范围。
  10. */
  11. public class SyncDemo2 {
  12. public static void main(String[] args) {
  13. Shop shop = new Shop();
  14. Thread t1 = new Thread(){
  15. public void run(){
  16. shop.buy();
  17. }
  18. };
  19. Thread t2 = new Thread(){
  20. public void run(){
  21. shop.buy();
  22. }
  23. };
  24. t1.start();
  25. t2.start();
  26. }
  27. }
  28. class Shop{
  29. public void buy(){
  30. /*
  31. 在方法上使用synchronized,那么同步监视器对象就是this。
  32. */
  33. // public synchronized void buy(){
  34. Thread t = Thread.currentThread();//获取运行该方法的线程
  35. try {
  36. System.out.println(t.getName()+":正在挑衣服...");
  37. Thread.sleep(5000);
  38. /*
  39. 使用同步块需要指定同步监视器对象,即:上锁的对象
  40. 这个对象可以是java中任何引用类型的实例,只要保证多个需要排队
  41. 执行该同步块中代码的线程看到的该对象是"同一个"即可
  42. */
  43. synchronized (this) {
  44. // synchronized (new Object()) {//没有效果!
  45. System.out.println(t.getName() + ":正在试衣服...");
  46. Thread.sleep(5000);
  47. }
  48. System.out.println(t.getName()+":结账离开");
  49. } catch (InterruptedException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. }

互斥锁

当多个线程执行不同的代码片段,但是这些代码片段之间不能同时运行时就要设置为互斥的.

使用synchronized锁定多个代码片段,并且指定的同步监视器是同一个时,这些代码片段之间就是互斥的.

  1. /**
  2. * 互斥锁
  3. * 当使用synchronized锁定多个不同的代码片段,并且指定的同步监视器对象相同时,
  4. * 这些代码片段之间就是互斥的,即:多个线程不能同时访问这些方法。
  5. */
  6. public class SyncDemo4 {
  7. public static void main(String[] args) {
  8. Foo foo = new Foo();
  9. Thread t1 = new Thread(){
  10. public void run(){
  11. foo.methodA();
  12. }
  13. };
  14. Thread t2 = new Thread(){
  15. public void run(){
  16. foo.methodB();
  17. }
  18. };
  19. t1.start();
  20. t2.start();
  21. }
  22. }
  23. class Foo{
  24. public synchronized void methodA(){
  25. Thread t = Thread.currentThread();
  26. try {
  27. System.out.println(t.getName()+":正在执行A方法...");
  28. Thread.sleep(5000);
  29. System.out.println(t.getName()+":执行A方法完毕!");
  30. } catch (InterruptedException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. public synchronized void methodB(){
  35. Thread t = Thread.currentThread();
  36. try {
  37. System.out.println(t.getName()+":正在执行B方法...");
  38. Thread.sleep(5000);
  39. System.out.println(t.getName()+":执行B方法完毕!");
  40. } catch (InterruptedException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }

总结

守护线程与普通线程的区别:守护线程是通过普通线程调用setDaemon(true)设置而来的

主要区别体现在当java进程中所有的普通线程都结束时进程会结束,在结束前会杀死所有还在运行的守 护线程

重点:多线程并发安全问题。

  • 什么是多线程并发安全问题:

        当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致执行顺序出现混乱。 解决办法:

        将并发操作改为同步操作就可有效的解决多线程并发安全问题

  • 同步与异步的概念:同步和异步都是说的多线程的执行方式。

        多线程各自执行各自的就是异步执行,而多线程执行出现了先后顺序进行就是同步执行

  • synchronized的两种用法

        1.直接在方法上声明,此时该方法称为同步方法,同步方法同时只能被一个线程执行

        2.同步块,推荐使用。同步块可以更准确的控制需要同步执行的代码片段。

        有效的缩小同步范围可以在保证并发安全的前提下提高并发效率

  • 互斥性

        当使用多个synchronized修饰了多个代码片段,并且指定的同步监视器都是同一个对象时,这些代 码片段就是互斥的,多个线程不能同时在这些代码片段上执行。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/322778
推荐阅读
相关标签
  

闽ICP备14008679号