[关闭]
@JunQiu 2019-10-30T08:43:18.000000Z 字数 4033 阅读 557

Java多进程与多线程

language_java 进程&线程 summary_2019/10


1、概述

2、多线程&多进程在Java中的运用

  1. ## 线程创建
  2. 可以通过继承Thread类,或者实现Runnable接口,本身Thread类实现了Runnable接口,无论哪种方式都需要实现run方法。
  3. 1)实现Runnable接口
  4. public class MyThread implements Runnable {
  5. private int count = 5;
  6. @Override
  7. public void run() {
  8. //...
  9. }
  10. }
  11. 2)继承Thread
  12. public class MyThread extends Thread {
  13. @Override
  14. public void run() {
  15. //...
  16. }
  17. }
  18. Tips: 关于Start方法
  19. Thread.java 类中的 start() 方法通知“线程规划器”此线程已经准备就绪,等待调用线程对象的 run() 方法。这个过程其实就是让系统安排一个时间来调用 Thread 中的 run() 方法,也就是使线程得到运行,多线程是异步的,线程在代码中启动的顺序不是线程被调用的顺序。

3、实例变量与线程安全

  1. 1、线程安全:关于线程安全最通俗的理解就是,当使用多线程和单线程的结果相同时,那么可以说程序是线程安全的。
  2. 2、实例变量共享:变量是否共享的关键在于是否是使用的同一个对象。
  3. 3synchronized关键字
  4. ## 实例1 - 实例变量共享
  5. public class MyThread extends Thread {
  6. private int count = 5;
  7. @Override
  8. public void run() {
  9. super.run();
  10. count--;
  11. System.out.println("由 " + MyThread.currentThread().getName() + " 计算,count=" + count);
  12. }
  13. }
  14. public class Run {
  15. public static void main(String[] args) {
  16. MyThread mythread=new MyThread();
  17. // 通过同一对象创建线程,使用的是同一个对象,实例变量共享
  18. Thread a=new Thread(mythread,"A");
  19. Thread b=new Thread(mythread,"B");
  20. Thread c=new Thread(mythread,"C");
  21. Thread d=new Thread(mythread,"D");
  22. Thread e=new Thread(mythread,"E");
  23. a.start();
  24. b.start();
  25. c.start();
  26. d.start();
  27. e.start();
  28. }
  29. }
  30. ## 实例1 - 实例变量不共享
  31. public class MyThread extends Thread {
  32. private int count = 5;
  33. public MyThread(String name) {
  34. super();
  35. this.setName(name);
  36. }
  37. @Override
  38. public void run() {
  39. super.run();
  40. while (count > 0) {
  41. count--;
  42. System.out.println("由 " + MyThread.currentThread().getName()
  43. + " 计算,count=" + count);
  44. }
  45. }
  46. }
  47. public class Run {
  48. public static void main(String[] args) {
  49. MyThread a = new MyThread("A");
  50. MyThread b = new MyThread("B");
  51. MyThread c = new MyThread("C");
  52. a.start();
  53. b.start();
  54. c.start();
  55. }
  56. }

3、常用方法

  1. 3.1 currentThread()
  2. 返回对当前正在执行的线程对象的引用。
  3. 3.2 getId()
  4. 返回此线程的标识符
  5. 3.3 getName()
  6. 返回此线程的名称
  7. 3.4 getPriority()
  8. 返回此线程的优先级
  9. 3.5 isAlive()
  10. 测试这个线程是否还处于活动状态。
  11. 什么是活动状态呢?
  12. 活动状态就是线程已经启动且尚未终止。线程处于正在运行或准备运行的状态。
  13. 3.6 sleep(long millis)
  14. 使当前正在执行的线程以指定的毫秒数“休眠”(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
  15. 3.7 interrupt()
  16. 中断这个线程。
  17. 3.8 interrupted() isInterrupted()
  18. interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能
  19. isInterrupted(): 测试线程Thread对相关是否已经是中断状态,但部清楚状态标志
  20. 3.9 setName(String name)
  21. 将此线程的名称更改为等于参数 name
  22. 3.10 isDaemon()
  23. 测试这个线程是否是守护线程。
  24. 3.11 setDaemon(boolean on)
  25. 将此线程标记为 daemon线程或用户线程。
  26. 3.12 join()
  27. 在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
  28. join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行
  29. 3.13 yield()
  30. yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU时间。注意:放弃的时间不确定,可能一会就会重新获得CPU时间片。
  31. 3.14 setPriority(int newPriority)
  32. 更改此线程的优先级

4、停止线程

  1. ## 正常情况下线程任务结束后,线程会自动停止,但是如果我们想手动结束进程我们可以采用下面的方法:
  2. 1stop(),suspend(),resume()这些方法已被弃用。
  3. 2interrupt()+ return
  4. public class MyThread extends Thread {
  5. @Override
  6. public void run() {
  7. try {
  8. for (int i=0; i<50000; i++){
  9. if (this.isInterrupted()) {
  10. return 0;
  11. }
  12. System.out.println(i);
  13. }
  14. } catch (Exception e) {
  15. e.printStackTrace();
  16. }
  17. }
  18. public static void main(String[] args) throws InterruptedException {
  19. MyThread myThread =new MyThread();
  20. myThread.start();
  21. Thread.sleep(100);
  22. myThread.interrupt();
  23. }
  24. }
  25. 3interrupt()+ 异常终止法
  26. public class MyThread extends Thread {
  27. @Override
  28. public void run() {
  29. try {
  30. for (int i=0; i<50000; i++){
  31. if (this.isInterrupted()) {
  32. System.out.println(" 已经是停止状态了!");
  33. throw new InterruptedException();
  34. }
  35. System.out.println(i);
  36. }
  37. System.out.println(" 不抛出异常,我会被执行的哦!");
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. public static void main(String[] args) throws InterruptedException {
  43. MyThread myThread =new MyThread();
  44. myThread.start();
  45. Thread.sleep(100);
  46. myThread.interrupt();
  47. }
  48. }

5、线程优先级

  1. ## 设置线程优先级有助于帮“线程规划器”确定在下一次选择哪一个线程来优先执行。
  2. 1、线程优先级具有继承性,比如 A 线程启动 B 线程,则 B 线程的优先级与 A 是一样的。
  3. 2、线程优先级具有规则性,线程的优先级与在代码中执行 start() 方法的顺序无关,与优先级大小有关。
  4. 3、线程优先级具有随机性,CPU尽量使线程优先级较高的先执行完,但无法百分百肯定。即线程优先级较高的不一定比线程优先级较低的先执行完。

6、线程分类

  1. 1、用户线程:运行在前台,执行具体的任务,如程序的主线程、连接网络的子线程等都是用户线程
  2. 2、守护线程:运行在后台,为其他前台线程服务.也可以说守护线程是JVM中非守护线程的 “佣人”。
  3. 特点:一旦所有用户线程都结束运行,守护线程会随JVM一起结束工作
  4. 应用:数据库连接池中的检测线程,JVM虚拟机启动后的检测线程
  5. 最常见的守护线程:垃圾回收线程
  6. 注意: setDaemon(true)必须在start()方法前执行,否则会抛出IllegalThreadStateException异常

7、参考文档

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注